【问题标题】:Does HibernateTemplate work with Envers? If so, how?HibernateTemplate 可以与 Envers 一起使用吗?如果是这样,怎么做?
【发布时间】:2023-04-10 02:41:01
【问题描述】:

我正在尝试在一个也使用 Hibernate 和 Spring 的项目中使用 Envers - 我非常感谢 HibernateTemplate 提供的代码缩减。

我在 JPA 下配置了 Envers,经过一些调整后,我能够获得由 EnversHibernateToolTask​​ Ant 任务(包括审计表)生成的模式。但是,当我编写如下代码时:

    hibernateTemplate.saveOrUpdate(f);

数据被持久化,但没有任何东西进入审计表。相反,如果我写:

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

然后数据进入审计表(但我宁愿使用前一种语法 - 我知道使用 JPA 的 EntityManager 将代码与 Hibernate 分离,但它简单并不能解决麻烦 - 更改 ORM 引擎并不是我最疯狂的这个项目的梦想。)

检查我的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>

这是我的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>

有没有人暗示这里发生了什么?谢谢!

【问题讨论】:

  • 请看下面我的cmets。

标签: java hibernate spring jpa hibernate-envers


【解决方案1】:

HibernateTemplate 有它的 JPA 对应物 JpaTemplate,它提供了非常相似的功能。

Envers 不能与 HibernateTemplate 一起使用的原因是因为它依赖于使用 EntityManager 时触发的 JPA 事件(您可以看到在上面的 persistence.xml 中声明的侦听器)。当使用 HibernateTemplate 时,理论上可以编写代码从 Hibernate 会话中触发这些事件,但它相当复杂。

【讨论】:

  • 优秀 - 使用 JpaTemplate 应该可以解决问题。它没有我想要的所有花里胡哨(特别是,我有一些代码需要进行分页,并通过 findByCriteria 完成,它允许对调用注入限制),但至少我有一个开始观点。谢谢!
  • 这有点像 hack,但是如果你将 JpaTemplate 的 exposeNativeEntityManager 设置为 true,你可以使用它的 executeFind() 方法将传递给 JpaCallbackEntityManager 转换为 HibernateEntityManager 并使用后者的getSession() 进行基于条件的查询。
  • 此外,在 Envers 1.2.1(最新版本)中,AuditEventListener 实现了常规的 Hibernate 事件侦听器,这意味着实际上应该可以将其配置为纯 Hibernate(无 JPA)。您需要摆脱 entityManagerFactorypersistence.xml 并使用 eventListeners 映射将所有侦听器配置为 sessionFactory 的一部分 - 查看 LocalSessionFactoryBean 了解详细信息;然后你就可以使用HibernateTemplate。请注意,我没有对此进行测试。
  • 嗯.... 必须检查这两种方法。我认为,如果我真的需要使用 Hibernate 功能,我宁愿完全放弃 JPA,但我会先尝试完成这一切,而不暴露 HibernateEntityManager 或尝试这样的新功能。谢谢。
【解决方案2】:

您只需将@Transactional 放入您的Dao 或调用dao.save()/ update 方法的服务中。

即使您注册了事件监听器,这些事件也不会被触发,除非您使用 Spring FW 的事务处理。 Spring 必须知道并告诉 hibernate 这些事件被触发。

【讨论】:

    猜你喜欢
    • 2019-03-11
    • 2015-06-24
    • 2012-04-08
    • 2021-06-30
    • 1970-01-01
    • 2011-01-21
    • 1970-01-01
    相关资源
    最近更新 更多