何年も前からGlassfish 3.1.1で正常に動作するJEE6アプリケーションがある場合。JEE7 / Glassfish 4.1.1 に移行する必要があり、JPA / Eclipselink に関するいくつかの問題に遭遇しました。
a)一方向の OneToMany 関係としてマップされた 2 つのリストを含むエンティティApplicantがあります。
@Entity
@Table(name="applicant")
@AttributeOverride(name="id", column=@Column(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;
}
}
これまでは、addKenntnis を使用して申請者に ITKentnis の新しいインスタンスを追加し、申請者を永続化するだけでした。Glassfish 4.1.1 ではエラーが発生します ->
javax.persistence.PersistenceException: 例外 [EclipseLink-4002] (Eclipse Persistence Services - 2.6.2.qualifier): org.eclipse.persistence.exceptions.DatabaseException Internal Exception: java.sql.SQLException: Field 'BewerberID' does not haveデフォルト値 エラーコード: 1364
フィールド「BewerberID」は、データベース テーブルの外部キーであり、null にすることはできず、この定義を変更できません。
これまでに見つけた唯一の回避策は、関係を双方向に再定義することでした。私は多くの関係を持ち、コードは JPA 2.0 で動作したため、より簡単な解決策があれば幸いです。
b) Applicant への一方向の @ManyToOne 関係を定義するエンティティApplicationがあります。
@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 ステートメントがあります ->
[#|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]
|#]
違いは、フィールド「BewerberID」を NULL にできないため、新しいサーバーでは INSERT が失敗することです。どういうわけかデータベースのチェックが違うようです。
同じことが、次の出力を持つ DELETE にも当てはまります ->
[#|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]
新しいサーバーには同じ更新ステートメント「UPDATE bewerbungen SET BewerberID = ?, ....」があるため、興味深いですが、null 制約ですぐに失敗します。