2016-04-25 116 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"> 

現在的插入和刪除之前的工作。 :)