Wenn eine JEE6-Anwendung, die seit Jahren auf Glassfish 3.1.1 funktioniert. Jetzt müssen sie JEE7/Glassfish 4.1.1 bewegen und lief in ein paar Probleme bei PPV/Eclipselink:JPA 2.1 unidirektionale OneToMany Mapping: EDITED
a) Ich habe eine Entität Antragsteller, die ein paar Listen enthält kartiert als unidirektionale OneToMany Beziehungen .
@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;
}
...
}
und das Unternehmen 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;
}
}
Bis jetzt habe ich einfach eine neue Instanz von ITKentnis dem Antragsteller mit addKenntnis und den Antragsteller bestehen blieb. 4.1.1 Mit Glassfish bekomme ich einen Fehler ->
javax.persistence.PersistenceException: Exception [Eclipselink-4002] (Eclipse-Persistence Services - 2.6.2.qualifier): org.eclipse.persistence.exceptions.DatabaseException Interne Ausnahme: java.sql.SQLException: Feld ‚BewerberID‘ hat keinen Standardwert Fehlercode: 1364
Das Feld „BewerberID“ ist ein Fremdschlüssel in der Datenbank-Tabelle, die nicht null sein kann, und Ich kann diese Definition nicht ändern.
Die einzige Problemumgehung, die ich bisher fand, war, die Beziehung zu bidirektional neu zu definieren. Da ich viele Beziehungen habe und der Code mit JPA 2.0 arbeitete, würde ich mich freuen, wenn es eine einfachere Lösung gäbe.
b) Ich habe eine Entität Anwendung, die eine unidirektionale @ ManyToOne-Beziehung zum Antragsteller definiert.
@Entity
@Table(name="bewerbungen")
public class Application extends BaseEntityVersioned implements Serializable {
...
// uni-directional
@ManyToOne (fetch=FetchType.LAZY)
@JoinColumn(name="BewerberID")
private Bewerberprofil bewerberprofil;
...
}
Unabhängig davon, ob dies ein gutes Design ist oder nicht (ich Gründe hatte es auf diese Weise abzubilden) -> wenn ich versuche, die Entität ich ein Update sehen zu löschen, die das Feld „BewerberID“ auf Null setzt, anstelle eines Löschens. Warum ist das in JPA 2.1 und wie kann ich das ändern?
Entschuldigung für die lange Post.
Thomas
EDIT: ich weitere Untersuchungen mit diesen Fragen gemacht, Debuggen, um die SQL-Anweisungen generiert am Glasfish 3.1.1. Server, der funktioniert.
ein neues Kind Entität Hinzufügen hat die folgenden SQL-Anweisungen, die die gleiche wie auf dem neuen Server sind ->
[#|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]
|#]
Der Unterschied ist, dass auf dem neuen Server die INSERT, da das Feld „BewerberID“ schlägt fehl kann nicht NULL sein. Irgendwie scheint der Check in der Datenbank anders zu sein.
Gleiches gilt für die DELETE ist die folgende Ausgabe hat ->
[#|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]
Das ist interressant, weil auf den neuen Server ich die gleiche Update-Anweisung "? UPDATE Bewerbungen SET BewerberID = ...." habe aber da scheitert es sofort mit der Nullbedingung!
Unidirektionale OneToMany-Beziehungen verwenden eine Join-Tabelle. Schlägst du vor, dass du es vorher ohne es funktioniert hattest? Siehe §2.10.5.1 der JPA-Spezifikation (2.0 oder 2.1) –
Ja, es funktioniert seit 2011 mit JPA2.0. Überprüfen Sie auch https://en.wikibooks.org/wiki/Java_Persistence/OneToMany unter Advanced. –
Siehe auch "Pro JPA 2" von Mike Keith Kapitel "Advanced Object-Relational Mapping": Vermeiden von Join-Tabellen Bis zu diesem Punkt haben wir ein unidirektionales Eins-zu-Viele-Mapping im Zusammenhang mit der Verwendung einer Join-Tabelle diskutiert Es ist auch möglich, eine unidirektionale Zuordnung ohne Verwendung einer Join-Tabelle zuzuordnen. Es erfordert, dass sich der Fremdschlüssel in der Ziel- Tabelle oder "viele" Seite der Beziehung befindet, obwohl das Zielobjekt keinen Verweis auf die "Eins" -Seite hat. Dies wird als unidirektionales Eins-zu-viele-Ziel-Fremdschlüssel-Mapping bezeichnet, da der Fremdschlüssel in der Zieltabelle statt einer ... –