Hibernate Interceptor mit Play 1.2.x

Update: Man beachte das PS!

Neulich wollte ich (möglichst generisch) wissen, welches Feld von einer Entity modifiziert wurde. Internet sagt, das ginge mit einem Interceptor:

Leider ist für Play nicht offensichtlich, wie man einen solchen einbindet… zumindest nicht für 1.2.x. Es gibt hibernate.ejb.interceptor, das ist es aber nicht. Tatsächlich gibt es “parallel” (“This property can not be combined with hibernate.ejb.interceptor”) noch hibernate.ejb.interceptor.session_scoped – und der geht:

Good to know: Man kann die Entity als solche hier nicht mehr ändern! Man kann aber das zu ändernde Property in currentState suchen und setzen (oder ergänzen) 🙂 Dann sollte man true zurückgeben, statt super.onFlushDirty(...). Quelle.

<Update>Interceptors haben noch einige andere nette Methoden, so kann man beispielsweise zentral checken, welche Entitäten geändert, inserted oder deleted worden sind.</Update>

PS: Internet sagt außerdem, dass Play schon einen eigenen Interceptor nutzen würde… klang für mich ein wenig so, als würde es Probleme geben, wenn man den “überschreibt” – ich konnte aber keine feststellen und das ist leider auch der Fall: im play.db.jpa.JPAPlugin wird ein eigener Interceptor verwendet, der dafür sorgt, dass Entitäten nicht automatisch gespeichert werden (Hibernate Standard?). Das bloße Verwenden eines eigenen Interceptors hebelt dies aus!

PPS: tgorres hat einen Workaround gefunden, siehe Kommentare. Vielen Dank dafür!

2 thoughts on “Hibernate Interceptor mit Play 1.2.x

  1. Ich hab ein bisschen gebastelt une eine Lösung gefunden. Plays Interceptor ist in der SessionFactory gespeichert, man kann also noch darauf zugreifen. Dann muss man nur noch alle Funktionsaufrufe an Plays Interceptor weiterleiten.

    public class ForwardingInterceptor implements Interceptor {
        private Interceptor next = EmptyInterceptor.INSTANCE;

        @Override
        public void afterTransactionBegin(Transaction tx) {
            next.afterTransactionBegin(tx);
        }
        // etc. für alle Methoden, jedesmal next.XYZ aufrufen
    }

    public class ModelFlushInterceptor extends ForwardingInterceptor {
        @Override
        public void afterTransactionBegin(Transaction tx) {
        HibernateEntityManagerFactory emFactory =
            (HibernateEntityManagerFactory) JPA.entityManagerFactory;
        SessionFactoryImplementor sessionFactory =
            (SessionFactoryImplementor) emFactory.getSessionFactory();
        Interceptor playInterceptor = sessionFactory.getInterceptor();

        setNext(playInterceptor);

        super.afterTransactionBegin(tx);
        }
    }

Leave a Reply

Your email address will not be published.

Ich erkläre mich damit einverstanden, dass alle eingegebenen Daten und meine IP-Adresse zum Zweck der Spamvermeidung durch das Programm Akismet in den USA überprüft und gespeichert werden. Weitere Informationen zu Akismet und Widerrufsmöglichkeiten.