Im Gegensatz zur textbasierten JPQL Abfragen sind Abfragen mit der Criteria API typsicher. Die meisten Fehler fallen deswegen schon zur Compilezeit und nicht erst zur Laufzeit auf. Bei der Abfrage eines bestimmten Feldes schreibt man dessen Namen aber als Zeichenkette, dadurch können sich auch bei der Criteria API Tippfehler einschleichen. Mit der Benutzung von Metamodels lässt sich das vermeiden.
Metamodels sind Klassen, die zu einem Entity erstellt werden. Metamodels heißen wie das entsprechnende Entity, nur mit einem Unterstrich am Ende. Sie können mit Eclipse oder über den Maven Build Prozess automatisch erzeugt werden. Über diese Klassen kann dann auf das jeweilige Feld des Entity zugegriffen werden. Deshalb müssen bei Abfragen keine Zeichenketten mehr benutzt werden.
Beispiel
Wie Metamodels benutzt werden, wird im folgenden Beispiel gezeigt. Da Frisbees, zumindest meiner Meinung nach, das beste Sportgerät sind, habe ich als Beispiel eine Datenbank erstellt und in dieser verschiedene Frisbees gespeichert. Das FrisbeeEntity hat als Felder Farbe (colour
) und Gewicht (weight
).
Wie jeder weiß, fliegen weiße Frisbee am Besten. Deswegen wollen wir wissen, welche der abgespeicherten Frisbees weiß sind. Die Abfrage mit der Criteria-API und ohne Metamodel sieht wie folgt aus:
In Zeile 31 wird nach dem Feld colour
gefragt. Da colour
ein String ist, können an dieser Stelle Tippfehler entstehen, die erst zur Laufzeit auffallen. Um das zu verbessern, müssen Metamodels benutzt werden.
Metamodels können automatisch generiert werden. Wie das genau funktioniert, steht unter dem Abschnitt “Erzeugung von Metamodels”. Dies ist sowohl mit Eclipse möglich, kann aber auch in den Maven Build Prozess eingebaut werden. Die Generierung mit Eclipse ist sehr einfach, ändert man allerdings das Entity, wird das zugehörige Metamodel nicht automatisch aktualisiert. Die Einbindung in den Maven Build Prozess erfordert zunächst ein bisschen mehr Aufwand, der sich aber auszahlt: Das Metamodel wird bei jedem Maven Build Prozess neu anhand des Entities erstellt.
Das Metamodel FrisbeeEntity_
sieht wie folgt aus:
Jetzt können wir in Zeile 31 den String colour
durch FrisbeeEntity_.colour
ersetzen:
Das Beispiel hat gezeigt, dass die Abfrage mit Metamodels weniger fehleranfällig ist.
Erzeugung von Metamodels mit Eclipse
Unter Projekt -> Properties
öffnet sich ein Fenster, in dem dann JPA ausgewählt werden kann. Unter Canonical metamodel lässt sich der Ordner auswählen, in dem die Metamodels gespeichert werden sollen. Mit einem Klick auf Apply
erstellt Eclipse zu jedem Entity des Projekts ein Metamodel.
Erzeugung von Metamodels mit Maven
Zur Erzeugung von Metamodels im Maven Build Prozess muss zunächst folgende dependency
hinzugefügt werden:
<dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-jpamodelgen</artifactId> <scope>compile</scope> <optional>true</optional> </dependency>
Zur Erstellung der Metamodels muss noch folgendes Plugin hinzugefügt werden:
<plugin> <groupId>org.bsc.maven</groupId> <artifactId>maven-processor-plugin</artifactId> <version>2.2.4</version> <executions> <execution> <id>process</id> <goals> <goal>process</goal> </goals> <phase>generate-sources</phase> <configuration> <outputDirectory>target/metamodel</outputDirectory> </configuration> </execution> </executions> </plugin>
Zum Hinzufügen der Metamodels als Sourcecode in Eclipse wird folgendes Plugin benötigt:
<plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>build-helper-maven-plugin</artifactId> <version>1.3</version> <executions> <execution> <id>add-source</id> <phase>generate-sources</phase> <goals> <goal>add-source</goal> </goals> <configuration> <sources> <source>target/metamodel</source> </sources> </configuration> </execution> </executions> </plugin>