2016-04-25 10 views
0

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!

+0

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) –

+0

Ja, es funktioniert seit 2011 mit JPA2.0. Überprüfen Sie auch https://en.wikibooks.org/wiki/Java_Persistence/OneToMany unter Advanced. –

+0

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 ... –

Antwort

0

Wie ich mit Hilfe von Chris Delahunt herausgefunden habe, ist das Problem kein Unterschied zwischen JPA 2.0 und 2.1, sondern eine Frage des Datenbank (Treiber) Verhaltens. Dies wurde auch durch die obigen SQL-Anweisungen impliziert.

Die Lösung war, dass ich nur die JDBC-Definition in Glsassfish 4.1.1 von

geändert
<jdbc-connection-pool datasource-classname="com.mysql.jdbc.jdbc2.optional.MysqlDataSource" name="Test" res-type="javax.sql.DataSource"> 

zu

<jdbc-connection-pool datasource-classname="com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource" name="Test" res-type="javax.sql.ConnectionPoolDataSource"> 

nun die Einfügungen und Löschungen Arbeit wie zuvor. :)

Verwandte Themen