2014-07-09 6 views
5

Ich versuche, die beste Möglichkeit zu finden, JPA im Zusammenhang mit einem erholsamen Webdienst zu verwenden. Die Eingabe kommt als JSON und ich kann Jackson/JAX-RS verwenden, um das zu einem POJO zu konvertieren. Dies wird an einen Dienst übergeben, wo ich irgendwie in eine JPA-Entität zusammenführen muss.Wie Eingabe von einem Webdienst zu einer JPA-Entität zusammengeführt wird

Dies sind die Optionen, die ich bisher mit Vor- und Nachteilen gefunden habe.

1. JPA merge()
Das erste, was ich versuchte, war wahrscheinlich die einfachste. Die GET-Aktion gibt die JPA-Entität zurück, die problemlos in JSON serialisiert werden kann. Bei der Aktualisierung wird das Objekt als JSON zurückgegeben, mit dem eine getrennte Entität gefüllt werden kann. Dies kann mit der JPA merge() -Methode in der Datenbank gespeichert werden.

Pros
einfache Architektur mit weniger Code-Duplizierung (das heißt kein DTO)

Cons
Soweit ich das funktioniert nur sagen kann, wenn man das ganze Modell um passieren. Wenn Sie versuchen, bestimmte Felder auszublenden, z. B. das Kennwort für eine Benutzerentität, denkt die Zusammenführung, dass Sie versuchen, diese Felder in der Datenbank auf Null zu setzen. Nicht gut!

2. DTO mit JPA finden() und Dozer
Next Ich dachte, ich bei Verwendung von Datentransferobjekte aussehen würde. Anscheinend ein Anti-Pattern, aber einen Blick wert. Der Dienst erstellt nun basierend auf der Entität eine DTO-Instanz, und dieses DTO wird in JSON serialisiert. Das Update ruft dann die Entität mithilfe einer find() -Methode aus der Datenbank ab, und die Werte müssen vom DTO in die Entität kopiert werden. Ich habe versucht, diese Zuordnung mit dem Dozer-Framework zu automatisieren.

Pros
Sie müssen nicht das gesamte Modell zurück. Wenn Sie bestimmte Felder haben, die nicht aktualisiert werden sollen, können Sie sie vom DTO entfernen und sie können nicht versehentlich in die Entität kopiert werden. Wenn Sie dozer verwenden, müssen Sie Attribute nicht manuell von dto in entity und umgekehrt kopieren.

Cons
Es fühlt sich an wie Sie selbst zu wiederholen, wenn die DTO zu schreiben. Irgendwie müssen Sie zwischen Entitäten und DTOs abbilden. Ich habe versucht, dies mit Dozer zu automatisieren, aber es war ein bisschen enttäuschend. Es gab Dinge aus, die es nicht hätte sein sollen und um die volle Kontrolle zu bekommen, musst du xml schreiben.

3. DTO mit manueller fusionieren
Einem dritten Weg Planierraupe zu verlassen wäre und kopieren Sie einfach die Eigenschaften gegenüber dem DTO an das Unternehmen in dem Dienst. Jeder scheint Anti-Pattern zu sagen, aber es ist so, wie jede nicht-triviale Anwendung, die ich in der Vergangenheit gesehen habe, funktioniert hat.

Zusammenfassung
Es scheint, eine Entscheidung zu sein, zwischen den Dinge einfach für den Entwickler zu halten, aber nicht die Kontrolle über den Ein-/Ausgang oder einen robustere Web-Service zu machen, sondern ein Anti-Muster in dem Verfahren zu verwenden. ..

Habe ich etwas verpasst?Vielleicht gibt es eine schwer fassbare Alternative?

Antwort

0

Die Verwendung von JPA merge sieht am einfachsten, saubersten und mit sehr wenig Aufwand, aber als korrekt erkannt erstellt Probleme mit abgesetzten Entitätsattribute auf Null gesetzt. Ein weiteres Problem, das in einer meiner Erfahrungen groß wurde, war, dass Sie, wenn Sie sich auf die JPA-Merge-Operation verlassen, auch die Cascade-Funktion verwenden müssen. Für einfache und weniger verschachtelte Relationen funktioniert das einigermaßen gut, aber für tief verschachtelte Domain-Objekte und viele Beziehungen hat dies einen großen Einfluss auf die Performance. Der Grund dafür ist, dass das ORM-Tool (Hibernate nach meiner Erfahrung) die SQL-Anweisung zum Laden der Merge-Entity ('Merge-Pfad' im Hibernate-Sprachgebrauch) zwischenspeichert. Wenn die Verschachtelung mit Cascade-Zuordnungen zu tief ist, werden die Joins in SQL zu groß. Das Markieren von Realitäten Lazy hilft hier nicht, da der Merge-Pfad durch die Cascades in Relationen bestimmt wird. Dieses Problem wird offensichtlich langsam als Ihr Modell entwickelt. Und die Aussicht auf wütende DBA, die eine riesige Join-Frage in unserem Gesicht winkten, veranlasste uns, etwas anderes zu tun :-) Es gibt eine interessante issue bezogen auf Hibernate in Bezug auf Zusammenführen von Lazy Relationen noch nicht gelöst (eigentlich abgelehnt, aber die Diskussion ist sehr angenehm zu lesen) in Hibernate JIRA.

Wir sind dann auf den DTO-Ansatz zugegangen, wo wir davon Abstand genommen haben, Merge zu verwenden, und uns darauf verlassen haben, es manuell zu tun. Ja, es war mühsam und erforderte das Wissen von , welcher Zustand tatsächlich von der abgelösten Entität kommt, aber zu uns war es wert. Auf diese Weise berühren wir nicht die Lazy-Relationen und Attribute, die nicht geändert werden sollen. und setze nur was benötigt wird. Die automatische Zustandserkennung von Hibernate erledigt den Rest beim Transaktions-Commit.

1

Dies ist Ansatz Ich verwende:

  • Unterdrückungs-Serialisierung bestimmter Felder mit XmlTransient Anmerkung
  • wenn die Aufzeichnung von der Client-Aktualisierung, die Einheit aus der Datenbank erhalten und ModelMapper mit benutzerdefinierter Eigenschaft Mapping verwenden, um Kopieren Sie die aktualisierten Werte, ohne die Felder zu ändern, die nicht in der JSON-Repräsentation enthalten sind.

Zum Beispiel:

public class User { 
    @Id 
    private long id; 

    private String email; 

    @XmlTransient 
    private String password; 
    ... 
} 

public class UserService { 
    ... 
    public User updateUser(User dto) { 
     User entity = em.find(User.class, dto.getId()); 
     ModelMapper modelMapper = new ModelMapper(); 
     modelMapper.addMappings(new UserMap()); 
     modelMapper.map(userDto, user); 
     return user; 
    } 
} 

public class UserMap extends PropertyMap<User, User> { 
    protected void configure() { 
     skip().setPassword(null); 
    } 
} 

BeanUtils ist eine Alternative zu ModelMapper.

Es wäre schön, wenn diese Bibliotheken die XmlTransient-Annotation erkennen könnten, so dass der Programmierer die Erstellung der benutzerdefinierten Eigenschaftszuordnung vermeiden kann.