JPA 2.1单向OneToMany映射:EDITED
如果有一个JEE6应用程序可以在Glassfish 3.1.1上运行良好,这是多年以来的事情。现在必须把它移到JEE7/Glassfish的4.1.1,撞上了几个问题就JPA/EclipseLink的:JPA 2.1单向OneToMany映射:EDITED
一)我有一个实体申请人包含映射为单向一对多关系几列。
@Entity
@Table(name="applicant")
@AttributeOverride(name="id", [email protected](name="UserID", insertable=false, updatable=false))
public class Applicant extends BaseEntityVersioned implements Serializable {
..
..
@OneToMany(cascade=CascadeType.ALL, orphanRemoval=true)
@JoinColumn(name="BewerberID", nullable=false)
private List<ITKenntnis> itKenntnisse = new ArrayList<ITKenntnis>();
..
public List<ITKenntnis> getITKenntnisse() {
return this.itKenntnisse;
}
public void setITKenntnisse(List<ITKenntnis> itKenntnisse) {
this.itKenntnisse = itKenntnisse;
}
public ITKenntnis createITKenntnis(){
return new ITKenntnis();
}
public boolean addITKenntnis(ITKenntnis itKenntnis) {
getITKenntnisse().add(itKenntnis);
return true;
}
...
}
与实体ITKEnntnis
@Entity
@Table(name="ITKenntnis")
public class ITKenntnis extends BaseEntityVersioned implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="ID")
private Integer id;
@Override
public Integer getId() {
return id;
}
@Override
public void setId(Integer id) {
this.id=id;
}
}
直到现在我只是增加ITKentnis的新实例申请人与addKenntnis并坚持申请人。 在GlassFish 4.1.1我得到一个错误 - >
javax.persistence.PersistenceException:异常[的EclipseLink-4002](Eclipse持久服务 - 2.6.2.qualifier):org.eclipse.persistence.exceptions.DatabaseException 内部异常:java.sql.SQLException中:字段“BewerberID”没有默认值 错误代码:1364
字段“BewerberID”在我的数据库表的外键不能为空,我无法改变这个定义。
到目前为止,我发现的唯一解决方法是将关系重新定义为双向。由于我有很多关系,并且代码与JPA 2.0一起工作,如果有更简单的解决方案,我将不胜感激。
b)我有一个实体应用程序,它定义了与申请人的单向@ ManyToOne关系。
@Entity
@Table(name="bewerbungen")
public class Application extends BaseEntityVersioned implements Serializable {
...
// uni-directional
@ManyToOne (fetch=FetchType.LAZY)
@JoinColumn(name="BewerberID")
private Bewerberprofil bewerberprofil;
...
}
无论阉这是一个很好的设计或没有(我的理由来映射这种方式) - >当我尝试删除我看到那台场“BewerberID”为null更新的实体,而不是删除。为什么在JPA 2.1中,我该如何改变它?
对不起,很长的文章。
托马斯
编辑: 我进行了进一步研究这些问题,调试对Glasfish 3.1.1生成的SQL语句。服务器正在工作。
添加新的子实体有哪些是一样的新服务器上下面的SQL语句 - 新服务器上的INSERT失败,因为该领域“BewerberID”>
[#|2016-04-26T17:22:55.613+0200|INFO|glassfish3.1.1|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=25;_ThreadName=Thread-2;|[EL Fine]: 2016-04-26 17:22:55.613--ClientSession(1645443748)--Connection(1826150217)--Thread(Thread[http-thread-pool-80(2),5,grizzly-kernel])--INSERT INTO bewerberedv (Bearbeitet, Bereich, Bewertung, Dauer, Kenntnis, Version, ZuletztVerwendet) VALUES (?, ?, ?, ?, ?, ?, ?)
bind => [true, 6, 1, null, 377, 2016-04-26 17:24:08.0, null]
|#]
[#|2016-04-26T17:22:55.628+0200|INFO|glassfish3.1.1|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=25;_ThreadName=Thread-2;|[EL Fine]: 2016-04-26 17:22:55.628--ClientSession(1645443748)--Connection(1826150217)--Thread(Thread[http-thread-pool-80(2),5,grizzly-kernel])--SELECT LAST_INSERT_ID()
|#]
[#|2016-04-26T17:22:55.644+0200|INFO|glassfish3.1.1|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=25;_ThreadName=Thread-2;|[EL Fine]: 2016-04-26 17:22:55.644--ClientSession(1645443748)--Connection(1826150217)--Thread(Thread[http-thread-pool-80(2),5,grizzly-kernel])--UPDATE bewerberedv SET BewerberID = ? WHERE (ID = ?)
bind => [2575, 1223970]
|#]
不同的是,不能为NULL。不知何故,数据库中的检查似乎有所不同。
同样对于删除的有以下输出 - >
[#|2016-04-26T17:13:39.363+0200|INFO|glassfish3.1.1|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=31;_ThreadName=Thread-2;|[EL Fine]: 2016-04-26 17:13:39.363--ClientSession(792940001)--Connection(1806567172)--Thread(Thread[http-thread-pool-80(4),5,grizzly-kernel])--UPDATE bewerbungen SET BewerberID = ?, PositionID = ?, InseratID = ?, Version = ? WHERE ((ID = ?) AND (Version = ?))
bind => [null, null, null, 2016-04-26 17:14:52.0, 1304157, 2016-04-26 17:14:25.0]
|#]
[#|2016-04-26T17:13:39.363+0200|INFO|glassfish3.1.1|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=31;_ThreadName=Thread-2;|[EL Fine]: 2016-04-26 17:13:39.363--ClientSession(792940001)--Connection(1806567172)--Thread(Thread[http-thread-pool-80(4),5,grizzly-kernel])--UPDATE inserateanz SET AnzahlBew = ?, AnzOffeneBewerbung = ?, AnzNeueBewerbung = ? WHERE (ID = ?)
bind => [0, 0, 0, 61277]
|#]
[#|2016-04-26T17:13:39.363+0200|INFO|glassfish3.1.1|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=31;_ThreadName=Thread-2;|[EL Fine]: 2016-04-26 17:13:39.363--ClientSession(792940001)--Connection(1806567172)--Thread(Thread[http-thread-pool-80(4),5,grizzly-kernel])--UPDATE positionenanz SET AnzahlBew = ?, AnzOffeneBewerbung = ?, AnzNeueBewerbung = ? WHERE (ID = ?)
bind => [0, 0, 0, 44726]
|#]
[#|2016-04-26T17:13:39.363+0200|INFO|glassfish3.1.1|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=31;_ThreadName=Thread-2;|[EL Fine]: 2016-04-26 17:13:39.363--ClientSession(792940001)--Connection(1806567172)--Thread(Thread[http-thread-pool-80(4),5,grizzly-kernel])--DELETE FROM bewerbungen WHERE ((ID = ?) AND (Version = ?))
bind => [1304157, 2016-04-26 17:14:52.0]
那interresting因为新的服务器我有同样的更新语句 “?UPDATE bewerbungen SET BewerberID = ....” 上,但在那里它立即失效,并带有空限制!
当我在Chris Delahunt的帮助下发现问题不是JPA 2.0和2.1之间的差异,而是数据库(驱动程序)行为的问题。这也是上述SQL语句所暗示的。
的解决方案是,我只是改变了JDBC定义在Glsassfish 4.1.1从
<jdbc-connection-pool datasource-classname="com.mysql.jdbc.jdbc2.optional.MysqlDataSource" name="Test" res-type="javax.sql.DataSource">
到
<jdbc-connection-pool datasource-classname="com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource" name="Test" res-type="javax.sql.ConnectionPoolDataSource">
现在的插入和删除之前的工作。 :)
Unidirectional OneToMany关系使用连接表。你是否暗示你之前没有这样做?请参阅JPA规范(2.0或2.1)的§2.10.5.1 –
是的,它自2011年起使用JPA2.0。还请查看高级下的https://en.wikibooks.org/wiki/Java_Persistence/OneToMany。 –
另请参见Mike Keith章节“高级对象关系映射”中的“Pro JPA 2”:避免连接表 到目前为止,我们已经讨论了使用连接表的上下文中的单向一对多映射,但它是 也可能映射单向映射而不使用连接表。它要求外键位于目标 表或关系的“多”一侧,即使目标对象没有任何对“one”一方的引用。 这被称为单向一对多目标外键映射,因为外键在目标表 而不是...... –