Question

J'essaie d'utiliser Envers sur un projet qui utilise également Hibernate et Spring - et j'apprécie beaucoup la réduction de code proposée par HibernateTemplate.

J'ai configuré Envers sous JPA et, après quelques ajustements, j'ai pu obtenir le schéma généré par la tâche Ant EnversHibernateToolTask ??(y compris les tables d'audit). Cependant, lorsque j'écris du code tel que:

    hibernateTemplate.saveOrUpdate(f);

les données sont persistées, mais rien ne va dans les tables d'audit. Inversement, si j’écris:

    EntityManager em = emf.createEntityManager();
    em.getTransaction().begin();
    em.persist(f);
    em.getTransaction().commit();

puis les données vont dans les tables d'audit (mais je préférerais utiliser l'ancienne syntaxe - je sais qu'en utilisant EntityManager de JPA, le code de Hibernate est découplé, mais cela ne paie pas l'argent sans tracas - le changement de moteur ORM n'est pas mon plus sauvage rêves pour ce projet.)

Il peut être utile de vérifier ma configuration applicationContext.xml :

<bean id="entityManagerFactory"
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="persistenceUnitName" value="projetox" />
    <property name="dataSource" ref="dataSource" />
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
            <property name="showSql" value="true" />
        </bean>
    </property>
</bean>
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>

<bean id="sessionFactory"
    class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="packagesToScan" value="com.w2it.projetox.model" />
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
        </props>
    </property>
</bean>

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
    destroy-method="close">
    ...
</bean>

et voici ma configuration persistence.xml :

<persistence-unit name="projetox" transaction-type="RESOURCE_LOCAL">
    <jta-data-source>java:/DefaultDS</jta-data-source>
    <properties>
        <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect" />
        <!--  Hibernate Envers -->
        <property name="hibernate.ejb.event.post-insert"
            value="org.hibernate.envers.event.AuditEventListener" />
        <property name="hibernate.ejb.event.post-update"
            value="org.hibernate.envers.event.AuditEventListener" />
        <property name="hibernate.ejb.event.post-delete"
            value="org.hibernate.envers.event.AuditEventListener" />
        <property name="hibernate.ejb.event.pre-collection-update"
            value="org.hibernate.envers.event.AuditEventListener" />
        <property name="hibernate.ejb.event.pre-collection-remove"
            value="org.hibernate.envers.event.AuditEventListener" />
        <property name="hibernate.ejb.event.post-collection-recreate"
            value="org.hibernate.envers.event.AuditEventListener" />
    </properties>
</persistence-unit>

Quelqu'un a-t-il une idée de ce qui se passe ici? Merci!

Était-ce utile?

La solution

HibernateTemplate a son équivalent JPA, JpaTemplate qui fournit une fonctionnalité assez similaire.

La raison pour laquelle Envers ne fonctionne pas avec HibernateTemplate, c'est parce qu'il repose sur des événements JPA (vous pouvez voir les écouteurs déclarés dans votre persistence.xml ci-dessus) déclenchés lorsque EntityManager est utilisé. En théorie, il est possible d'écrire du code pour déclencher ces événements à partir d'une session Hibernate lorsque HibernateTemplate est utilisé, mais c'est plutôt compliqué.

Autres conseils

Tout ce que vous deviez faire était de mettre @Transactional dans votre Dao ou dans vos services qui appellent les méthodes dao.save () / update.

Même si vous enregistrez votre eventlistener, ces événements ne sont pas déclenchés à moins que vous utilisiez le transcendant du Spring FW. Le printemps doit savoir et dire en veille que ces événements sont déclenchés.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top