【问题标题】:Spring Data JPA On JBoss - Data Not Written To DatabaseJBoss 上的 Spring Data JPA - 数据未写入数据库
【发布时间】:2018-03-23 12:43:06
【问题描述】:

我正在将一个大型项目从 EJB 实体 bean 慢慢升级到 Spring Data JPA。最初的努力是使用 Spring Data 1.6.6、JPA 2.0、Spring Framework 3.2.14。我在单元测试中转换了一些 bean 并使用 H2 数据库。

现在我正在尝试部署到 JBoss 5.2 并且数据没有提交到数据库。我有一个 EntityListener 并且调用了 PrePersist 方法,但没有调用 PostPersist。因此,不知何故,Hibernate 将它们作为托管 bean,但它们从未提交给数据库。我尝试使用不同的传播添加@Transaction,但实体仍未写入数据库。我假设我的配置以某种方式缺少实体管理器与事务的连接。我研究了其他帖子,但没有找到任何有效的组合。这是我的配置:

    <!-- Create default configuration for Hibernate -->
<bean id="hibernateJpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
    <property name="databasePlatform" value="${hibernate.dialect:org.hibernate.dialect.Oracle10gDialect}"/>
    <property name="showSql" value="false"/>
</bean>

<bean id="entityManagerFactory"
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="dataSource" ref="springbatch.repositoryDataSource" />
    <property name="jpaVendorAdapter" ref="hibernateJpaVendorAdapter" />
    <property name="jpaProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
            <prop key="hibernate.transaction.factory_class">org.hibernate.transaction.JTATransactionFactory</prop>
            <prop key="hibernate.transaction.manager_lookup_class">org.hibernate.transaction.JBossTransactionManagerLookup</prop>
            <prop key="hibernate.transaction.auto_close_session">true </prop>
            <prop key="hibernate.current_session_context_class">jta</prop>
            <prop key="hibernate.connection.release_mode">auto</prop>
            <prop key="hibernate.show_sql">true</prop>
            <prop key="hibernate.format_sql">true</prop>
            <prop key="hibernate.transaction.jta.platform">org.hibernate.service.jta.platform.internal.JBossStandAloneJtaPlatform</prop>
        </props>
    </property>
    <property name="packagesToScan">
        <list>
            <value>com.*</value>
        </list>
    </property>
</bean>

<!-- Transaction Manager -->
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"> 
    <property name="transactionManagerName" value="java:/TransactionManager" />
    <property name="userTransactionName" value="UserTransaction" />
    <property name="allowCustomIsolationLevels" value="true"/>
</bean>

<jpa:repositories base-package="com.*" factory-class="com.stoneriver.powersuite.persistence.repository.BaseRepositoryFactoryBean" />

<!-- bean post-processor for JPA annotations -->
<bean id="persistenceExceptionTranslationPostProcessor"
    class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />

<!-- bean post-processor for JPA annotations -->
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>

谁能给我一些建议?

谢谢

这是保存 1 个实体的日志记录:

2018-03-25 16:45:49,826 DEBUG [org.springframework.transaction.jta.JtaTransactionManager] (http-0.0.0.0-8080-9) Participating in existing transaction
2018-03-25 16:45:49,828 TRACE [org.springframework.transaction.support.TransactionSynchronizationManager] (http-0.0.0.0-8080-9) Initializing transaction synchronization
2018-03-25 16:45:49,830 TRACE [org.springframework.transaction.interceptor.TransactionInterceptor] (http-0.0.0.0-8080-9) Getting transaction for [com.stoneriver.powersuite.persistence.repository.BaseRepositoryImpl.save]
2018-03-25 16:45:49,832 DEBUG [org.springframework.orm.jpa.EntityManagerFactoryUtils] (http-0.0.0.0-8080-9) Opening JPA EntityManager
2018-03-25 16:45:49,838 DEBUG [org.springframework.orm.jpa.EntityManagerFactoryUtils] (http-0.0.0.0-8080-9) Registering transaction synchronization for JPA EntityManager
2018-03-25 16:45:49,841 TRACE [org.springframework.transaction.support.TransactionSynchronizationManager] (http-0.0.0.0-8080-9) Bound value [org.springframework.orm.jpa.EntityManagerHolder@71f03e27] for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@7bcd0210] to thread [http-0.0.0.0-8080-9]
2018-03-25 16:45:49,848 INFO  [com.stoneriver.powersuite.persistence.listeners.RecordIdEntityListener] (http-0.0.0.0-8080-9) onPrePersist : com.taliantsoftware.rulesengine.conditionevaluator.ejb.ExpressionBean .... id: 10032005
2018-03-25 16:45:49,923 INFO  [com.stoneriver.powersuite.persistence.repository.BaseRepositoryImpl] (http-0.0.0.0-8080-9) Saved ExpressionBean with Id : 10032005
2018-03-25 16:45:49,926 TRACE [org.springframework.transaction.interceptor.TransactionInterceptor] (http-0.0.0.0-8080-9) Completing transaction for [com.stoneriver.powersuite.persistence.repository.BaseRepositoryImpl.save]
2018-03-25 16:45:49,928 TRACE [org.springframework.transaction.jta.JtaTransactionManager] (http-0.0.0.0-8080-9) Triggering beforeCommit synchronization
2018-03-25 16:45:49,929 TRACE [org.springframework.transaction.jta.JtaTransactionManager] (http-0.0.0.0-8080-9) Triggering beforeCompletion synchronization
2018-03-25 16:45:49,931 TRACE [org.springframework.transaction.support.TransactionSynchronizationManager] (http-0.0.0.0-8080-9) Removed value [org.springframework.orm.jpa.EntityManagerHolder@71f03e27] for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@7bcd0210] from thread [http-0.0.0.0-8080-9]
2018-03-25 16:45:49,933 DEBUG [org.springframework.orm.jpa.EntityManagerFactoryUtils] (http-0.0.0.0-8080-9) Closing JPA EntityManager
2018-03-25 16:45:49,935 TRACE [org.springframework.transaction.jta.JtaTransactionManager] (http-0.0.0.0-8080-9) Triggering afterCommit synchronization
2018-03-25 16:45:49,936 DEBUG [org.springframework.transaction.jta.JtaTransactionManager] (http-0.0.0.0-8080-9) Registering after-completion synchronization with existing JTA transaction
2018-03-25 16:45:49,938 TRACE [org.springframework.transaction.support.TransactionSynchronizationManager] (http-0.0.0.0-8080-9) Clearing transaction synchronization
2018-03-25 16:45:49,941 TRACE [org.springframework.transaction.support.TransactionSynchronizationManager] (http-0.0.0.0-8080-9) Removed value [org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$DefaultCrudMethodMetadata@a2d7c25] for key [public abstract java.lang.Object com.stoneriver.powersuite.persistence.repository.BaseRepository.save(java.lang.Object)] from thread [http-0.0.0.0-8080-9]

【问题讨论】:

  • 你如何测试/知道实体(不)被写入数据库?
  • 当前的测试方法(将在我们完全脱离实体 bean 时更新)使用仙人掌。所以我正在通过仙人掌进行单元测试。不使用 Spring Unit Test Runner ...从我读到的内容中,那是需要 @Rollback(false) 的部分。所以要确认一下,我没有看到调用了 PostUpdate 实体侦听器,并且数据不在数据库中。如果我从 save() 更改为 saveAndFlush(),它将被写入数据库。这种方法使 EJB 客户端代码的转换变得复杂。所以我想在事务提交时写出信息。
  • 我刚刚查看了当前代码,在调用 JPA 存储库之前,调用流程中存在一个无状态会话 bean(需要事务)

标签: jboss spring-data spring-data-jpa


【解决方案1】:

听起来您遇到了典型的 JPA 挑战:JPA 在刷新事件(也包含在提交中)之前几乎什么都不做。所以你需要在你的测试中添加一些事务管理。

可能最简单的方法是使用 Spring Test Runner,如果您想在测试后保持数据库状态@Rollback(false)

【讨论】:

  • 通过仙人掌的测试执行在没有弹簧数据的情况下工作正常。测试执行调用控制事务的会话 EJB。因此,理论上 spring 数据应该使用与 EJB 2.1 实体 bean 相同的事务语义来执行。
  • 我增加了事务日志,这里是保存日志
【解决方案2】:

在阅读了我使用的版本的hibernate源代码后,这些更改解决了问题。

<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="jtaDataSource" ref="springbatch.repositoryDataSource" />
<property name="jpaVendorAdapter" ref="hibernateJpaVendorAdapter" />
<property name="jpaProperties">
    <props>
        <prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
        <prop key="hibernate.transaction.factory_class">org.hibernate.transaction.JTATransactionFactory</prop>
        <prop key="hibernate.transaction.manager_lookup_class">org.hibernate.transaction.JBossTransactionManagerLookup</prop>
        <prop key="hibernate.transaction.auto_close_session">true </prop>
        <prop key="hibernate.current_session_context_class">jta</prop>
        <prop key="hibernate.connection.release_mode">auto</prop>
        <prop key="hibernate.show_sql">true</prop>
        <prop key="hibernate.format_sql">true</prop>
        <prop key="hibernate.transaction.jta.platform">org.hibernate.service.jta.platform.internal.JBossStandAloneJtaPlatform</prop>
    </props>
</property>
<property name="packagesToScan">
    <list>
        <value>com.*</value>
    </list>
</property>

具体来说

<property name="jtaDataSource" ref="springbatch.repositoryDataSource" />

<prop key="hibernate.transaction.manager_lookup_class">org.hibernate.transaction.JBossTransactionManagerLookup</prop>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-11-17
    • 1970-01-01
    • 2021-10-26
    • 2021-03-05
    • 2015-10-07
    • 2012-04-11
    • 2019-07-24
    相关资源
    最近更新 更多