web-dev-qa-db-ja.com

SpringBootおよびSpringDataJPAを使用したHibernateインターセプターまたはリスナー

オブジェクトの子のコレクションを保存する前に、いくつかのチェックを実行したいと思います(cascade = all)。

私はSpringBootとSpringData JPAを使用していて、Hibernateリスナーとインターセプターのどちらのアプローチが最適か疑問に思っていました。それぞれの長所/短所は何ですか?あなたが最善のアプローチと考えるものの例をたまたま持っていますか?

次のようにXMLで構成する前に、Hibernateリスナーを使用しました。

    <property name="eventListeners">
        <map>
            <entry key="post-update">
                <list>
                    <ref bean="myListener" />
                </list>
            </entry>
        </map>
    </property>

セッションファクトリ(古いプロジェクト)。しかし、今ではほとんどの構成がアノテーションに含まれており(Spring Bootが原因)、構成をできるだけシンプルで軽量に保ちたいので、インターセプターの方が良い解決策になるかもしれません。

ありがとうございました。

6
ccc

私は自分でこれをよく調べて、私が働いたことを共有したいと思いました(私は下部に役立つ(非インライン)リンクを含めました)。

インターセプター

インターセプターを使用するには、 _org.hibernate.EmptyInterceptor_ クラスを拡張し、インターセプトするメソッドをオーバーライドします。あなたはおそらくあなたの場合 onSave(...) が欲しいでしょう。

_package foo.bar;

import org.hibernate.EmptyInterceptor;
import org.hibernate.type.Type;
import Java.io.Serializable;

public class MyInterceptor extends EmptyInterceptor {
    @Override
    public boolean onSave(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) {
        // do your checks here
        return false;
    }
}
_

インターセプターを登録する Spring/Hibernateに登録する必要があります。 application.propertiesまたはapplication.yml でこれを行うことができます。

_spring:
  jpa:
    properties:
      hibernate.ejb.interceptor: foo.bar.MyInterceptor
_

インターセプターの利点は、コードが(潜在的に)少なく、構成が比較的単純なことです。欠点は、アプリケーション全体で1つしか持てず、APIの操作が混乱する可能性があることです。

Event Listener

イベントの場合、Hibernateの_org.hibernate.event.spi.*Listener_インターフェースの1つを実装します。あなたはおそらくあなたの場合 _org.hibernate.event.spi.PreInsertEventListener_ が欲しいでしょう。

イベントをEventListenerRegistryに登録する必要があります。これを行うには、クラスを_@Component_、_@Autowire_をクラスにEntityManagerFactoryにし、_@PostConstruct_メソッドを作成してクラスを登録します。

_package foo.bar;

import org.hibernate.event.service.spi.EventListenerRegistry;
import org.hibernate.event.spi.EventType;
import org.hibernate.event.spi.PreInsertEvent;
import org.hibernate.event.spi.PreInsertEventListener;
import org.hibernate.internal.SessionFactoryImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.persistence.EntityManagerFactory;

@Component
public class MyEventListener implements PreInsertEventListener {
    @Autowired
    private EntityManagerFactory entityManagerFactory;

    @PostConstruct
    private void init() {
        SessionFactoryImpl sessionFactory = entityManagerFactory.unwrap(SessionFactoryImpl.class);
        EventListenerRegistry registry = sessionFactory.getServiceRegistry().getService(EventListenerRegistry.class);
        registry.getEventListenerGroup(EventType.PRE_INSERT).appendListener(this);
    }

    @Override
    public boolean onPreInsert(PreInsertEvent preInsertEvent) {
        // do your checks here
        return false;
    }
}
_

リスナーの利点は、必要な数だけ持つことができ、APIはインターセプターよりも優れており、コードと構成がすべて1か所にあることです。欠点は、構成長く、より複雑になることです。


27

こんにちは

まず、次のことを確認できます:https://www.baeldung.com/database-auditing-jpaここでは、すべてのオプションが詳細に説明されています。

私は個人的にHibernate Interceptorをお勧めします。使いやすく、理解しやすいものです。プロジェクトの複雑さに応じて、ほとんどの場合それは行います。

アプリケーションでこれを構成するには、次を追加する必要があります:spring.jpa.properties.hibernate.ejb.interceptor = path.to.interceptor( application.properties内)。インターセプター自体は@ Componentである必要があります。

インターセプターが実際にBeanを使用しない限り。それ以外の場合は少し複雑ですが、解決策を提供できれば幸いです。

Application-test.propertiesにEmptyInterceptorを追加して、ログシステム(または使用したいもの)を使用しないようにすることを忘れないでください。テスト(これはあまり役に立ちません)。

これがお役に立てば幸いです。

最後の注意として:常にSpring/Hibernateバージョンを更新してください(可能な限り最新のものを使用してください)そして、ほとんどのコードが新しいバージョンとして冗長になることがわかります可能な限り構成を減らすようにしてください。

3
Rareș Flueraș