2016-04-25 114 views
0

如果有一个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 = ....” 上,但在那里它立即失效,并带有空限制!

+0

Unidirectional OneToMany关系使用连接表。你是否暗示你之前没有这样做?请参阅JPA规范(2.0或2.1)的§2.10.5.1 –

+0

是的,它自2011年起使用JPA2.0。还请查看高级下的https://en.wikibooks.org/wiki/Java_Persistence/OneToMany。 –

+0

另请参见Mike Keith章节“高级对象关系映射”中的“Pro JPA 2”:避免连接表 到目前为止,我们已经讨论了使用连接表的上下文中的单向一对多映射,但它是 也可能映射单向映射而不使用连接表。它要求外键位于目标 表或关系的“多”一侧,即使目标对象没有任何对“one”一方的引用。 这被称为单向一对多目标外键映射,因为外键在目标表 而不是...... –

回答

0

当我在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"> 

现在的插入和删除之前的工作。 :)