2013-04-05 20 views
9

Ich bin neu in der ganzen JPA-Sache, also habe ich mehrere Fragen über die beste Art, JPA-Zusammenführung zu behandeln und zu bestehen.Der beste Weg, JPA Merge zu behandeln?

  1. Ich habe ein Benutzerobjekt, das aktualisiert werden sollte (einige Werte wie Datum und Name). Muss ich das übergebene Objekt zuerst zusammenführen oder ist es sicherer, das neue Objekt zu finden?

    Derzeit mein Code ein Benutzer für die Aktualisierung wie folgt aussieht:

    public void updateUserName(User user, String name) { 
        // maybe first merge it? 
        user.setName(name); 
        user.setChangeDate(new Date()); 
        em.merge(user); 
    } 
    

    Wie kann ich sicher sein, dass der Benutzer, bevor das Update-Methode aufgerufen wird nicht manipuliert wurde? Ist es sicherer, so etwas zu tun:

    Vielleicht andere Lösungen? Ich habe mir mehrere Videos angesehen und viele Beispiele gesehen, aber sie waren alle unterschiedlich und niemand erklärte, was die beste Praxis ist.

  2. Was ist der beste Ansatz, um Kinder Beziehungen hinzuzufügen? Zum Beispiel hat mein Benutzerobjekt eine Verbindung zu mehreren Gruppen. Soll ich den JPA-Handler für Benutzer aufrufen und die neue Gruppe einfach zur Benutzergruppenliste hinzufügen oder soll ich die Gruppe in einem so group-Handler mit persist anlegen und manuell zu meinem Benutzerobjekt hinzufügen?

Hoffnung jemand hier hat eine Ahnung;)

+0

Siehe http://stackoverflow.com/questions/1069992/jpa-entitymanager-why-use-persist-over-merge – GKislin

Antwort

3

Frage 1

  • Die merge Methode muss auf einem abgelöst Einheit aufgerufen werden.
  • Die merge-Methode gibt das zusammengefügte Objekt an an den EntityManager zurück.

Was bedeutet das?

Eine Entität wird getrennt, sobald der EntityManager, den Sie zum Abrufen verwenden, geschlossen wird. (d. h. die meiste Zeit, weil Sie es in einer vorherigen Transaktion abrufen).

In Ihrem zweiten Code-Beispiel: Benutzer ist angehängt (weil Sie es gerade holen) und so Aufruf Merge ist nutzlos. (BTW: es ist nicht getReference aber find)

In Ihrem ersten Beispiel: Wir kennen nicht den Zustand des Benutzers (losgelöstes Wesen oder nicht?). Wenn es losgelöst ist, ist es sinnvoll, merge zu rufen, aber vorsichtig, dass merge sein Objekt nicht als ein Argument übergeben ändern. So, hier ist meine Version Ihrer ersten Probe:

/** 
* @param user : a detached entity 
* @return : the attached updated entity 
**/ 
public User updateUserName(User user, String name) { 
    user.setName(name); 
    user.setChangeDate(new Date()); 
    return em.merge(user); 
} 

Frage 2

Vielleicht sind einige Code-Beispiel zu erklären, was Sie von JPA-Handler bedeuten können uns Ihr Anliegen zu verstehen helfen. Wie auch immer, ich werde versuchen dir zu helfen.

Wenn Sie einen persistenten Benutzer, und Sie müssen eine neue Gruppe erstellen und mit dem persistenten Benutzer zuzuordnet:

User user = em.find(User.class, userId); 
Group group = new Group(); 
... 
em.persist(group); 
user.addToGroups(group); 
group.addToUsers(user); //JPA won't update the other side of the relationship 
         //so you have to do it by hand OR being aware of that 

Wenn Sie einen persistenten Benutzer und eine persistente Gruppe und Sie müssen sie assoziieren :

User user = em.find(User.class, userId); 
Group group = em.find(Group.class, groupId); 
... 
user.addToGroups(group); 
group.addToUsers(user); 

Allgemeine Überlegungen

Die beste Praktiken in Bezug auf all dies hängt wirklich davon ab, dass Sie die Transaktionen (und damit den Lebenszyklus des EntityManagers) im Vergleich zum Lebenszyklus Ihrer Objekte verwalten.

Die meiste Zeit: ein EntityManager ist ein wirklich kurzlebiges Objekt. Auf der anderen Seite können Ihre Geschäftsobjekte länger leben und Sie müssen daher Zusammenführen aufrufen (und darauf achten, dass die Zusammenführung das Objekt, das im Argument übergeben wird, nicht ändert !!!).

Sie können entscheiden, Ihre Geschäftsobjekte in derselben Transaktion (d. H. Mit demselben EntityManager) abzurufen und zu ändern: es bedeutet viel mehr Datenbankzugriff und diese Strategie muss aus Leistungsgründen in der Regel mit einem Second-Level-Cache kombiniert werden. Aber in diesem Fall müssen Sie die Zusammenführung nicht aufrufen.

Ich hoffe diese Hilfe.

+0

Vielen Dank für Ihre Antwort. In Bezug auf meine Frage 1, ist es nicht der einfachste Weg, meine Felder wie date und new name in meiner Methode zu setzen, die den JPA-Handler aufruft und einfach eine Methode "updateUser (User user)" aufruft, um das Benutzerobjekt einfach zusammenzuführen Speichern Sie alle Änderungen, anstatt Methoden für mehrere Update-Anwendungsfälle zu erstellen. – ManuPanu

6
  1. Es hängt davon ab, was Sie erreichen möchten und wie viele Informationen Sie über den Ursprung des Objekts haben, das Sie zusammenführen möchten.

    Erstens, wenn Sie em.merge(user) in der ersten Zeile Ihrer Methode aufrufen oder am Ende ist es egal. Wenn Sie JTA und CMT verwenden, wird Ihre Entität aktualisiert, wenn der Methodenaufruf beendet wird. Der einzige Unterschied besteht darin, dass, wenn Sie em.merge(user) aufrufen, bevor der Benutzer Ändern Sie den zurückgegebenen Instanz statt Ihrer Parameter verwenden sollte, so ist es entweder:

    public void updateUserName(User user, String name) { 
        User managedUser = em.merge(user); 
        managedUser.setChangeDate(new Date()); 
        // no need of additional em.merge(-) here. 
        // JTA automatically commits the transaction for this business method. 
    } 
    

    oder

    public void updateUserName(User user, String name) { 
        user.setChangeDate(new Date()); 
        em.merge(user); 
        // JTA automatically commits the transaction for this business method. 
    } 
    

    Jetzt über Entität zu aktualisieren.
    Wenn Sie nur einige gut definierte Felder in Ihrer Entität aktualisieren möchten, verwenden Sie die zweite Methode, da diese sicherer ist. Sie können nicht sicher sein, ob ein Client Ihrer Methode einige andere Felder Ihrer Entität nicht geändert hat. Daher werden sie auch von em.merge(-) aktualisiert, was möglicherweise nicht das ist, was Sie erreichen wollten.

    Auf der anderen Seite - wenn Sie alle Änderungen durch den Benutzer akzeptieren wollen und nur außer Kraft setzen/einige Eigenschaften wie changeDate in Ihrem Beispiel hinzufügen, ist der erste Ansatz auch in Ordnung (ganze Einheit an die Business-Methode übergeben fusionieren.) Es hängt wirklich von Ihrem Anwendungsfall ab.

  2. Ich denke, es hängt von Ihren kaskadierenden Einstellungen ab. Wenn Sie alle Elemente Groups automatisch aktualisieren oder zusammenführen möchten, wenn die Entität User geändert wird, können Sie sie einfach zur Sammlung des Benutzers hinzufügen (etwa User#addGroup(Group g) { groups.add(g)}). Wenn Sie keine Kaskadierung wünschen, können Sie immer eigene Methoden erstellen, die propagieren auf der anderen Seite der Beziehung.Es könnte etwa so aussehen: User#addGroup(Group g), die automatisch g.addUser(this); aufruft.

Verwandte Themen