web-dev-qa-db-fra.com

eventlisteners utilisant Hibernate 4.0 avec Spring 3.1.0.release?

Ces fichiers jar sont tous deux récents et offrent les solutions les plus récentes pour les applications Java EE. Mais j'ai un problème pour spécifier des écouteurs en veille prolongée dans hibernate.cfg.xml.

Avant le printemps 3.1.0, LocalSessionFactroyBean détenait un attribut qui conserve les eventlisteners. Mais avec 3.1.0.release, il n’existe pas de carte eventlisteners. Maintenant, je ne parviens pas à garder la trace des objets modaux lors de la sauvegarde, du post-chargement, etc., car ils ne sont pas configurés par Spring. Avez-vous une idée pour résoudre ce problème?

19
asyard

J'ai eu le même problème frustrant. Hibernate 4 semble avoir fondamentalement changé votre façon de vous inscrire aux événements et le groupe Spring n'a pas encore rattrapé son retard. Voici ma solution basée sur les annotations utilisant une méthode init pour enregistrer un écouteur:

@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);
    }
}

Un intercepteur serait une autre bonne approche, mais le support pour les intercepteurs a été supprimé par erreur: https://jira.springsource.org/browse/SPR-8940

34
nano

La nouvelle approche consiste à utiliser un intégrateur pour enregistrer les écouteurs d'événements. Hibernate utilisera maintenant la découverte de service pour enregistrer des écouteurs d’événements et voici comment j’ai réussi à l’utiliser avec un maven archetype-webapp

créez un fichier sous META-INF/services (qui devrait résider dans votre répertoire de ressources), appelé org.hibernate.integrator.spi.Integrator avec toutes les classes qui implémentent l'interface hibernate spi, une ligne chacune. Petit exemple ci-dessous:

...

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
            ...
        }
    }

    ...
}

Toute entité devant avoir cet événement enregistré doit implémenter MyPersistableEntity (non affichée ici).

13
David Kago

Vous pouvez vérifier le billet Hibernate [1]: https://hibernate.onjira.com/browse/HHH-6945

Le guide de migration dit: 

hibernate.cfg.xml n'est plus pris en charge en tant que moyen de spécifier des auditeurs . La nouvelle approche consiste à utiliser un Org.hibernate.integrator.spi.Integrator qui fonctionne sur la base de la "découverte de service ".

Et vous pouvez obtenir les instructions complètes @ http://in.relation.to/Bloggers/EventListenerRegistration

Les liens dans le ticket ont un problème, utilisez ce qui suit:

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

J'espère que cela aidera quelqu'un à chercher des réponses à ce problème.

4

Lorsque vous ajoutez des écouteurs d'événements personnalisés via la classe EventListenerRegistry, comme indiqué dans les réponses ci-dessus, vous devez vous assurer que les écouteurs d'événements par défaut sont supprimés. Sinon, si dans votre application il y a une correspondance entre plusieurs cartes, une exception "Exception Hibernate: références partagées à la collection: xyz" sera levée.

0
Dinesh Angolkar