Blog

Blog

Neues aus unserem Blog

Spielend leichter Umgang mit JPA-Entities in Vaadin

Jochen Just Montag, 09. Februar 2015 @ 09:34 geschrieben von Jochen Just

In vielen Anwendungen will man die eine oder andere JPA-Entity darstellen. Sei es zur Entwicklung einer CRUD-Anwendung. Sei es im RAD-Stil, um zu Beginn des Projekts eine Entity schnell sichtbar machen zu können und sie später über eine spezialisierte Ansicht anzuzeigen. Sei es, man braucht eine tabellarische Darstellung der Instanzen einer Entity.

Zu diesem Zweck gibt es für das Vaadin-Framework das Add-On Vaadin JPAContainer.

Das Add-On bietet viele Vorteile:

  • leicht zu verwenden
  • in Verbindung mit einer Tabelle sind alle Spalten direkt sortierbar
  • von Haus aus mit Lazy-Loading ausgestattet, d.h. die Anzeige von 100.000 Entities in einer Table lädt nicht alle Entities in den Speicher, sondern nur einen kleinen Ausschnitt und lädt nach, wenn mehr Daten anzuzeigen sind
  • Filtern ist möglich, um nur eine Untermenge aller Entities anzuzeigen
  • Daten landen automatisch in einem Cache, um unnötige Roundtrips zur Datenbank zu vermeiden
  • das Add-On wird direkt vom Vaadin-Hersteller angeboten. Es ist daher gut gepflegt und bleibt dies wahrscheinlich auch für die nächste Zukunft

Codebeispiel:

// Erzeugt eine Vaadin-Tabelle, die
// 1. alle Eigenschaften der Entity SampleData als Spalten anzeigt
// 2. sortierbare Spalten hat
// 3. Lazy-Loading implementiert, um Scrollen durch große Datenmengen
//    speicherfreundlich und schnell ermöglichen

final JPAContainer<SampleData> container =
   JPAContainerFactory.makeReadOnly(SampleData.class, entityManager);
final Table table = new Table("Table");
table.setContainerDataSource(container);

layout.addComponent(table);

// Sorgt dafür, dass nur noch SampleDatas angezeigt werden,
// deren Bean-Property 'name' größer gleich "Danny DeVito" ist
final Filter filter = Filters.gte ("name", "Danny DeVito");
container.addContainerFilter (filter);

 

Es gibt aber auch Nachteile, die man nicht verschweigen sollte:

  • Komplexe Filter-Vorhaben müssen u.U. mit dem Interface QueryModifierDelegate realisiert werden. Das wäre nicht weiter tragisch. Aber bei dessen Verwendung wird auf Caching verzichtet. Das macht sich in der Performance (z.B. Hin- und Her-Scrollen in einer Tabelle) leider deutlich bemerkbar. Vermeiden kann man das Ausschalten des Cachings, indem man 2 Dinge beachtet (Quelle dieser Information: com.vaadin.addon.jpacontainer.provider.CachingSupport#isCachingPossible(EntityContainer))
    • Das QueryModifierDelegate nicht dem JPAContainer setzen, sondern dem zugehörigen EntityProvider (jpaContainer.getEntityProvider().setQueryModifierDelegate(queryModifierDelegate);)
    • In der Implementierung des QueryModifierDelegates darauf achten, dass die Methode filtersWillBeAdded(CriteriaBuilder,CriteriaQuery<?>,List<Predicate>) von der oben erwähnten Klasse CachingSupport mit drei null Werten aufgerufen wird. Wirft die Implementierung dann eine NullPointerException, ist Caching nicht möglich.
  • Der Container ist ausschließlich dazu da mit JPA zu arbeiten. Benötigt man zum Filtern von Daten Dinge, die nicht über JPA möglich sind (z.B. ein UNION), muss man einen anderen Container verwenden.
  • Filter werden in JPA-Predicates automatisch umgewandelt. Aber es gibt keine offiziellen Weg, eigene Filter und deren Umwandlung in JPA-Predicates zu definieren. Die zugehörige Logik ist leider in privaten statischen Methoden und Variablen umgesetzt.

CRUD-Funktionalität

Das Add-On bringt über die Klasse com.vaadin.addon.jpacontainer.fieldfactory.FieldFactory die Grundlagen für eine CRUD-Anwendung mit. Über diese Klasse kann man spielend leicht eine Form erzeugen, die für alle Eigenschaften einer Entity automatisch entsprechende HTML-Elemente erzeugt, mit denen die Werte verändert werden können.

Insgesamt eine runde Sache, wobei meiner Meinung nach 2 Einschränkungen existieren:

  1. Für einfache Anwendungsfälle ganz brauchbar, aber sobald Relations (OneToMany, ManyToOne etc.) ins Spiel kommen, ist das Standardverhalten schlecht bedienbar. Z.B. werden bei einer ManyToOne-Relation alle bean-Properties der Many-Entities angezeigt. Das Beispiel unten zeigt, dass bereits mit acht Eigenschaften die UI nicht mehr allzu übersichtlich ist.. 
  2. Bedient zur Zeit nur die deprecated Klasse com.vaadin.ui.Form. Deren Ersatz com.vaadin.data.fieldgroup.FieldGroup nebst dessen Interface com.vaadin.data.fieldgroup.FieldGroupFieldFactory wird nicht unterstützt.

Allerdings lässt sich das Standardverhalten mit wenig Aufwand anpassen, so dass wir in einem unserer Kundenprojekte innerhalb kurzer Zeit eine CRUD-Oberfläche für alle Entities im System erstellen konnten.

 

 


Abschließend kann ich nur sagen, dass dieses Vaadin-Add-On sehr hilfreich ist, um sehr schnell zu guten und wartbaren Ergebnissen zu kommen. Wenn es die Anforderungen (siehe Nachteile oben) erlauben, den JPAContainer einsetzen zu können.

 

 


zur Übersicht

Willkommen auf dem avono Blog

Hier auf dem avono Blog finden Sie in regelmäßigen Abständen sowohl technische Neuigkeiten aus unserer Partnerproduktwelt als auch nützliche Entwicklertipps.
Und jetzt kommt der obligatorische Disclaimer: Die Ausführungen der Blogeinträge spiegeln nicht die Meinung der avono AG sondern nur die Sicht der einzelnen Autoren wider.

Weitere Blogeinträge