web-dev-qa-db-ja.com

イベントリスナーは、Hibernate 4.0とSpring 3.1.0.releaseを使用していますか?

これらのjarはどちらも新しくリリースされ、Java EEアプリケーションの最新のソリューションを備えています。しかし、hibernate.cfg.xmlでhibernateリスナーを指定することに問題があります。

Spring 3.1.0より前は、LocalSessionFactroyBeanはイベントリスナーを保持する属性を保持していました。しかし、3.1.0.releaseでは、eventlistenersマップはありません。モーダルオブジェクトは、Springによって構成されていないため、saveorupdate、postloadなどで追跡できません。この問題を解決するアイデアはありますか?

19
asyard

私は同じイライラする問題を抱えていました。 Hibernate 4はイベントへの登録方法を根本的に変えたようで、Springグループはまだ追いついていません。これは、リスナーを登録するためにinitメソッドを使用する、注釈ベースのソリューションです。

@Component
public class HibernateEventWiring {

    @Autowired
    private SessionFactory sessionFactory;

    @Autowired
    private SomeHibernateListener listener;

    @PostConstruct
    public void registerListeners() {
        EventListenerRegistry registry = ((SessionFactoryImpl) sessionFactory).getServiceRegistry().getService(
        EventListenerRegistry.class);
        registry.getEventListenerGroup(EventType.POST_COMMIT_INSERT).appendListener(listener);
        registry.getEventListenerGroup(EventType.POST_COMMIT_UPDATE).appendListener(listener);
    }
}

インターセプターは別の素晴らしいアプローチですが、インターセプターのサポートが誤って削除されました: https://jira.springsource.org/browse/SPR-894

34
nano

新しいアプローチは、Integratorを使用してイベントリスナーを登録することです。 Hibernateは、イベントリスナーの登録にサービスディスカバリを使用します。Mavenのarchetype-webappを使用して、Hibernateを動作させる方法は次のとおりです。

mETA-INF/services(リソースディレクトリの下にある必要があります)の下にorg.hibernate.integrator.spi.Integratorと呼ばれるファイルを作成し、Hibernate spiインターフェースを実装するすべてのクラスを1行ずつ作成します。以下の短い例:

...

META-INF/services/org.hibernate.integrator.spi.Integrator

com.example.CustomIntegrator

com.example.CustomIntegrator

package com.example;

import ...;

public void CustomIntegrator implements Integrator {

    static final Logger logger = LoggerFactory.getLogger(CustomIntegrator.class);

    @Override
    public void integrate(Configuration configuration, SessionFactoryImplementor implementor, SessionFactoryServiceRegistry registry) {
        final EventListenerRegistry eventRegistry = registry.getService(EventListenerRegistry.class);

        logger.info("Registering event listeners");
        // you can add duplication strategory for duplicate registrations
        ...

        // prepend to register before or append to register after
        // this example will register a persist event listener
        eventRegistry.prependListeners(EventType.PERSIST, myListener);
        ...
    }

    ...

}

com.example.MyListener

package com.example;

import ...

public class MyListener implements PersistEventListener {

    static final Logger logger = LoggerFactory.getLogger(MyListener.class);

    public void onPersist(PersistEvent event) throws HibernateException {
        logger.debug("Entering MyListener");

        if(event.getObject() instanceof MyPersistableEntity) {
            MyPersistableEntity entity = (MyPersistableEntity) event.getObject();
            // do something with entity
            ...
        }
    }

    ...
}

このイベントを登録する必要があるエンティティは、MyPersistableEntityを実装する必要があります(ここには表示されていません)

13
David Kago

Hibernateチケット[1]を確認したいと思うかもしれません: https://hibernate.onjira.com/browse/HHH-6945

移行ガイドは言う:

hibernate.cfg.xmlは、リスナーを指定する手段としてサポートされなくなりました。 「サービス検出」に基づいて機能するorg.hibernate.integrator.spi.Integratorを使用する新しいアプローチが導入されました。

そして、完全な指示を取得できます@ http://in.relation.to/Bloggers/EventListenerRegistration

チケット内のリンクには問題があります。以下を使用してください:

https://github.com/hibernate/hibernate-orm/blob/master/hibernate-envers/src/main/Java/org/hibernate/envers/event/EnversIntegrator.Java

https://github.com/hibernate/hibernate-orm/blob/master/hibernate-envers/src/main/resources/META-INF/services/org.hibernate.integrator.spi.Integrator

これがこの問題の答えを探している人に役立つことを願っています。

上記の応答で述べたように、EventListenerRegistryクラスを介してカスタムイベントリスナーを追加する場合、デフォルトのイベントリスナーが削除されていることを確認する必要があります。それ以外の場合、アプリケーションにonetomanyマッピングがあると、「Hibernate例外:コレクションへの共有参照:xyz」例外がスローされます。

0
Dinesh Angolkar