JPA mit JTA: Persist entity-und merge-Kaskaden-Kind-Entitäten

Habe ich eine bidirektionale eins-zu-viele-Beziehung mit den folgenden Entitäten:

0 oder 1 client <-> 0 oder mehr Bestellungen von Produkten

Beim speichern des client-Entität, möchte ich das Produkt, um Entitäten beibehalten werden, auch (als deren Fremdschlüssel auf die "Eltern" - client können aktualisiert worden sein).

Natürlich alle erforderlichen CASCADE-Optionen auf der client-Seite. Aber es funktioniert nicht, wenn eine neu erstellte client persistiert wird zum ersten mal während der Referenzierung eines bereits bestehenden Produktes, um wie in diesem Szenario:

  1. Produkt bestellen '1' erzeugt und persistiert. Funktioniert einwandfrei.
  2. client '2' angelegt und ein Produkt, um '1' ist Hinzugefügt, um seine Produkt-Aufträge-Liste. Dann ist es permanent. Funktioniert nicht.

Ich habe versucht, mehrere apporaches, aber keiner von Ihnen zeigte das erwartete Ergebnis. Sehen die Ergebnisse unter. Ich Lesen Sie alle Fragen hier, aber Sie wollten mir nicht helfen. Ich benutze EclipseLink 2.3.0, reines JPA 2.0 Annotations, und JTA-transaction-Typ, die auf einem Apache Derby (JavaDB) in-memory DB auf GlassFish 3.1.2. Entität Beziehungen verwaltet werden, die von einer JSF-GUI. Objekt-Ebene-relationship-management-funktioniert (abgesehen von persistierenden), getestet habe ich es mit JUnit-tests.

Ansatz 1) "Standard" (basiert auf NetBeans-Klassen-templates)

Client:

@Entity
public class Client implements Serializable, ParentEntity {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @OneToMany(mappedBy = "client", cascade={CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH},
            fetch= FetchType.LAZY)
    private List<ProductOrder> orders = new ArrayList<>();

    //other fields, getters and setters
}

ProductOrder:

@Entity
public class ProductOrder implements Serializable, ChildEntity {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @ManyToOne //owning side
    private Client client;

    //other fields, getters and setters
}

Generische Persistenz Fassade:

//Called when pressing "save" on the "create new..." JSF page
public void create(T entity) {
    getEntityManager().persist(entity);
}

//Called when pressing "save" on the "edit..." JSF page
public void edit(T entity) {
    getEntityManager().merge(entity);
}

Ergebnis:

create() wirft diese Ausnahme sofort:

Achtung: Eine Ausnahme ist aufgetreten, während eine Anrufung auf EJB
ClientFacade Methode public void
javaee6test.Bohnen.AbstractFacade.erstellen(java.lang.Objekt)
javax.ejb.EJBException: Transaktion abgebrochen ...

Verursacht durch:
javax.die Transaktion.RollbackException: Transaktion gekennzeichnet sind, für die das rollback.
...

Verursacht durch: Exception [EclipseLink-4002] (Eclipse Persistence
Dienstleistungen - 2.3.0.v20110604-r9504):
org.eclipse.die Persistenz.Ausnahmen.DatabaseException Internal
Ausnahme: java.sql.SQLIntegrityConstraintViolationException:
Anweisung wurde abgebrochen, weil es würde verursacht haben einen doppelten Schlüssel
Wert in einer unique-oder primary key-Einschränkung oder einen eindeutigen index identifiziert
durch 'SQL120513133540930' definiert 'PRODUCTORDER'. Error Code: -1
Aufruf: INSERT INTO PRODUCTORDER (ID, CLIENT_ID) VALUES (?, ?) binden =>
[2 Parameter gebunden] Query:
InsertObjectQuery(javaee6test.Modell.ProductOrder[ id=1 ]) ...

Verursacht durch:
java.sql.SQLIntegrityConstraintViolationException: Die Aussage war
abgebrochen, weil es würde verursacht haben einen doppelten Schlüsselwert in einer einzigartigen
oder primary key-Einschränkung oder einen eindeutigen index gekennzeichnet durch
'SQL120513133540930' definiert 'PRO-DUCTORDER'. ...

Verursacht durch:
org.apache.derby.client.bin.SqlException: Die Anweisung wurde abgebrochen
werden-die es verursachen würde verursacht haben einen doppelten Schlüssel, Wert in einer unique-oder
primary key-Einschränkung oder einen eindeutigen index gekennzeichnet durch
'SQL120513133540930' definiert 'PRODUCTOR-DER'.

Ich verstehe nicht diese Ausnahme. Bearbeiten() funktioniert Prima. ABER ich möchte hinzufügen, Produkt-Aufträge zu einem Kunden in seine Erstellung Zeit, so ist dies unzureichend.

Ansatz 2) merge() nur

Änderungen Generische Persistenz Fassade:

//Called when pressing "save" on the "create new..." JSF page
public void create(T entity) {
    getEntityManager().merge(entity);
}

//Called when pressing "save" on the "edit..." JSF page
public void edit(T entity) {
    getEntityManager().merge(entity);
}

Ergebnis:

Create(), die EclipseLink-Logging-Ausgabe, sagt:

Fein: INSERT INTO KUNDEN (ID, NAME, ADDRESS_ID) VALUES (?, ?, ?)
binden => [3 Parameter gebunden]

aber KEIN "UPDATE" auf der Produkt-Tabelle. So, die Beziehung ist nicht etabliert. Wieder "Bearbeiten" (), auf der anderen Seite, funktioniert gut.

Apporach 3) Id GenerationType.IDENTITÄT auf beiden entity-Typen

Änderungen an client-und Produkt bestellen, Klasse:

...
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
...

Ergebnis:

Create(), die EclipseLink-Logging-Ausgabe, sagt:

Fein: INSERT INTO KUNDEN (NAME, ADDRESS_ID) VALUES (?, ?) binden => [2
Parameter gebunden]

Fein: Werte IDENTITY_VAL_LOCAL()

Fein: INSERT INTO
PRODUCTORDER ("ORDERDATE", CLIENT_ID) VALUES (?, ?) binden => [2
Parameter gebunden]

Fein: Werte IDENTITY_VAL_LOCAL()

also statt estabilshing eine Beziehung zu dem Produkt Hinzugefügt, um die client-Liste, ein neues Produkt, um entity wird erstellt und persistiert (!) und eine Beziehung zu dieser Entität ist estabilshed. Hier gilt das gleiche, Bearbeiten() funktioniert Prima.

Apporach 4) Ansatz (2) und (3) kombiniert

Ergebnis: die Gleichen wie im Ansatz (2).

Meine Frage ist: gibt es eine Möglichkeit zu erkennen, das oben beschriebene Szenario? Wie kann es werden erreicht? Ich möchte bleiben mit JPA (kein vendor-spezifische Lösung).

InformationsquelleAutor der Frage SputNick | 2012-06-14

Schreibe einen Kommentar