【问题标题】:EntityManager from LocalContainerEntityManagerFactoryBean does not persist entities into the databaseLocalContainerEntityManagerFactoryBean 中的 EntityManager 不会将实体持久化到数据库中
【发布时间】:2013-05-07 13:44:13
【问题描述】:

问题是在 Spring 托管 bean 中注入 @PersistenceContextEntityManager 不会将实体持久化到数据库中。我尝试在AddDao bean 上使用@Transactional,其中调用了entityManager.persist()(我已启用注释驱动的事务)。

事务从另一个 bean 开始,该 bean 由 Camel 在 Camel Java DSL 中用 .transacted() 实例化。该 bean 有一个 @Autowired 属性,它是 DAO,并具有注入 @PersistenceContextEntityManager

使用Bitronix作为事务管理器。

Spring xml 配置文件的一部分如下所示:

  <bean id="localContainerEntityManagerFactoryBean" depends-on="btmConfig" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="jtaDataSource" ref="dataSource"/>
    <property name="persistenceUnitName" value="nameFromPersistenceXml"/>
    <property name="persistenceProvider">
        <bean class="org.hibernate.ejb.HibernatePersistence"/>
    </property>
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
    </property>
    <property name="jpaDialect">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/>
    </property>
    <property name="packagesToScan" value="package with @Entity POJOs"/>

  </bean>



  <bean id="btmConfig" factory-method="getConfiguration"
      class="bitronix.tm.TransactionManagerServices">
    <property name="serverId" value="spring-btm" />
  </bean>

  <!-- create BTM transaction manager -->
  <bean id="BitronixTransactionManager" factory-method="getTransactionManager"
      class="bitronix.tm.TransactionManagerServices" depends-on="btmConfig"
      destroy-method="shutdown" />
  <!-- Spring JtaTransactionManager -->
  <bean id="springTransactionManager"
      class="org.springframework.transaction.jta.JtaTransactionManager">
    <property name="transactionManager" ref="BitronixTransactionManager" />
    <property name="userTransaction" ref="BitronixTransactionManager" />
  </bean>

  <tx:annotation-driven transaction-manager="springTransactionManager" />

编辑:在过于简化的版本中,它看起来像这样:

在 Camel Java DSL 中有

from("wsLayer")
   .transacted()
   .otherProcessing()
   .to("bean:addBean?method=addMyEntity")

添加 bean 看起来像这样:

@Component
public class AddBean {
    @Autowired
    private AddDao addDao;

    public void addMyEntity(MyEntity myEntity) {
        //other business logic
        addDao.persistMyEntity(myEntity);
    }
}

@Component
public class AddDao {
    @PersistenceContext
    private EntityManager entityManager;

    //I have tried here 
    //@Transactional and 
    //@Transactional(propagation = PropagationType.REQUIRES_NEW)
    public void persistMyEntity(MyEntity myEntity) {
        entityManager.persist(myEntity);
    }
}

从数据库中读取效果很好。

查看数据源:

<bean id="dataSource" class="bitronix.tm.resource.jdbc.PoolingDataSource"
    init-method="init" destroy-method="close">
    <property name="uniqueName" value="theName" />
    <property name="maxPoolSize" ><value>${db.pool.maxSize}</value></property>
    <property name="minPoolSize" ><value>${db.pool.minSize}</value></property>    
    <property name="allowLocalTransactions" ><value>true</value></property>
    <property name="automaticEnlistingEnabled" ><value>true</value></property>
    <property name="className" ><value>${db.pool.datasource}</value></property>
    <property name="driverProperties" ref="databaseProperties" />
</bean>

属性在 Maven 的pom.xml 中设置如下:

 db.pool.maxSize=15
 db.pool.maxSize=5
 db.pool.datasource=org.postgresql.xa.PGXADataSource

【问题讨论】:

  • 你没有把你试图坚持的实体的代码放在你的帖子中,这可能是一个“大对象”的情况吗?检查此link。希望能帮助到你。编辑:我找到了this
  • 实际上它不会保留任何域对象,无论是大的还是小的。它将它们持久化到缓存/实体管理器而不是数据库(顺便说一句是 PostgreSQL);在调用em.persist(entity)em.contains(entity) 之后立即结果为真,但entity 实际上并没有持久化到数据库中。我猜这与交易有关。关于链接,对象被正常映射,事务是persistence.xml 中的JTA,而不是那里讨论的RESOURCE_LOCAL

标签: java spring jpa transactions apache-camel


【解决方案1】:

您是否尝试在 em.persist(entity) 之后执行 em.flush()? 根据 Java EE 的文档:

em.persist(entity):使一个实例被管理和持久化。 但 em.flush(entity):将持久化上下文同步到底层数据库。

所以,你可以这样做:

em.persist(myEntity);
em.flush();

并检查此更改是否有所作为。

【讨论】:

  • 我试过了,这没有任何区别;我没试过的是em.merge(entity),我会试试的。
  • 它也不适用于em.merge(entity) 之后有或没有em.flush()
【解决方案2】:

从给出的有限症状来看,JTA 事务似乎没有启动和传播。您的 EM 在某种程度上可以正常工作 - 从 DB 读取,允许针对其持久上下文缓存进行数据更改,但从不写入 DB。

认为这是一个配置问题,您的 @Transaction 注释被忽略了。

我已启用注释驱动的事务。

确保它在你的 Spring 配置中配置如下:

<tx:annotation-driven transaction-manager="springTransactionManager"/>

地点:

xmlns:tx="http://www.springframework.org/schema/tx"

【讨论】:

  • 这正是问题所在。交易应该是由骆驼创建的。除了命名空间之外,xsi:schemaLocation 中还有 http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
【解决方案3】:

因此,根据apache camel jpa 文档,您必须放置一个描述方法行为的 URI,它描述了一个选项“flushOnSend”,也许您必须添加该 URI。 Here 它描述了一个使用 Hibernate 的示例。 而here 是一个测试类,也许你可以使用它并检查你是否没有通过任何;-)

【讨论】:

  • 我们不使用 Camel JPA 组件,而是使用 Bean 组件。在 Camel Java DSL 中没有 from(wherever).process()[...].to("jpa:[entityClassName][?options]") 而是 from(wherever).transacted().[...].to("bean:addBean?method=addEntity")addBean 具有 @AutowiredaddDao bean,它已将 EntityManager 注入 @PersistenceContext
【解决方案4】:

以这种方式尝试@Transactional

@Component
public class AddDao {
    @PersistenceContext
    private EntityManager entityManager;

    @Transactional("BitronixTransactionManager")
    public void persistMyEntity(MyEntity myEntity) {
        entityManager.persist(myEntity);
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-11-27
    • 1970-01-01
    • 2012-01-30
    • 2016-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-11
    相关资源
    最近更新 更多