JPA und Bean Validation – ein Paar mit verschiedenen Ansichten

Bean Validation ist genial – zumindest meistens: Instanzvariablen oder Property-Getter von Domänenobjekten können einfach mittels Annotationen mit Regeln – Constraints – versehen werden, um bspw. auszudrücken, dass ein Feld nicht leer bleiben darf (@NotNull String name) oder bestimmte Wertebereiche nicht verlassen darf (@Min(18) int age).

Geprüft werden die Constraints dann z. B. in JSF-Eingabeformularen oder beim Speichern von JPA-Entities. Zudem ist eine explizite Validierung per API möglich. Da bleiben eigentlich kaum Wünsche offen, wenn da nicht eine recht eigenwillige – man könnte auch sagen „unsinnige“ – Regelung in der JPA-Spezifikation zum Grübeln anregen würde:

Die JPA-Spezifikation verlangt von JPA-Providern, dass sie die Validität von in der Datenbank einzutragenden Objekten vor der Speicherung überprüfen, und zwar „upon the
pre-persist, pre-update, and pre-remove lifecycle … events“ (Abschnitt 3.6.1 der Spec.).

Die Referenzimplementierung EclipseLink hält sich da auch sklavisch dran, was aber im Falle der Neuanlage eines DB-Eintrags einigermaßen sinnbefreit ist: Wird ein transientes Objekt an EntityManager.persist übergeben, geschieht die Prüfung in diesem Moment und ungültige Objekte werden abgelehnt (via ConstraintViolationException). Ändert man das Objekt in der Folge, aber noch vor dem Commit, wird nicht etwa nochmals geprüft! Dadurch können also (hoffentlich unbewusst) ungültige Daten in die DB gelangen. Auf der sicheren Seite ist man nur, wenn man vor dem Commit explizit EntityManager.flush aufruft. Dann wird nämlich erneut geprüft …

Es kommt aber noch schlimmer: Bean Validation erlaubt auch Constraints auf Properties, die nicht Teil der persistenten View eines JPA-Objektes sind. So könnte z. B. für ein Objekt mit Field Access – bei dem also die Instanzvariablen auf DB-Spalten gemapped werden – eine Methode namens isValid mit Bean Validation Constraintzs versehen sein, um bspw. feldübergreifende Gültigkeitsregeln zu prüfen. EclipseLink ruft diese Validierunsmethode nur dann auf, wenn es zumindest ein BV Constraint auf einem persistenten Feld gibt. Es macht den Eindruck, als hätte da jemand ein bisschen über-optimiert …

Hibernate auf der anderen Seite verhält sich absolut sinnvoll: BV Constraints werden immer vor dem eigentlichen DB-Eintrag geprüft. Das entspricht zwar nicht den Worten der Spezifikation, verhindert aber ungültige Einträge in der DB, was ja wohl der Sinn und Zweck der Angelegenheit ist.

Wenn Sie’s ausprobieren wollen: Unter https://github.com/GEDOPLAN/jpa-bv-demo finden Sie ein Demo-Projekt, das mittels Maven-Profilen zwischen EclipseLink und Hibernate umgeschaltet werden kann.

Advertisements

Über Dirk Weil
Dirk Weil ist seit 1998 als Berater im Bereich Java tätig. Als Geschäftsführer der GEDOPLAN GmbH in Bielefeld ist er für die Konzeption und Realisierung von Informationssystemen auf Basis von Java EE verantwortlich. Seine langjährige Erfahrung in der Entwicklung anspruchsvoller Unternehmenslösungen machen ihn zu einem kompetenten Ansprechpartner und anerkannten Experten auf dem Gebiet Java EE. Er ist Autor in Fachmagazinen, hält Vorträge und leitet Seminare und Workshops aus einem eigenen Java-Curriculum.

2 Responses to JPA und Bean Validation – ein Paar mit verschiedenen Ansichten

  1. Tobias says:

    Hallo,
    vielen Dank für diesen interessanten Blogeintrag.

    Ich würde diesen Blog gern über den RSS-Feed lesen, aber leider ist er veraltet und die neuen Blogeinträge tauchen dort nicht mehr auf. Mir scheint die letzte Aktualisierung ist am
    Tue, 15 Dec 2015 10:09:47 +0000 erfolgt.

    Besten Gruß,
    Tobias

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s

%d Bloggern gefällt das: