LocalContainerEntityManagerFactoryBean中的EntityManager不会将实体持久保存到数据库中

时间:2013-05-07 13:44:14

标签: java spring jpa transactions apache-camel

问题是在Spring托管bean中注入EntityManager的{​​{1}}不会将实体持久存储到数据库中。我尝试在@PersistenceContext bean上使用@Transactional,其中AddDao被调用(我启用了注释驱动的事务)。

事务开始于另一个bean,Camel在Camel Java DSL中用entityManager.persist()实例化。该bean具有.transacted()属性,该属性是DAO并且@Autowired注入了EntityManager

使用事务管理器Bitronix。

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

@PersistenceContext

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

在Camel Java DSL中有

  <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" />

添加bean看起来像这样:

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

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

查看数据来源:

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

其中属性在Maven的<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> 中设置如下:

pom.xml

4 个答案:

答案 0 :(得分:2)

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

em.persist(entity):使实例成为托管和持久的。 但 em.flush(entity):将持久化上下文与底层数据库同步。

所以,你可以这样做:

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

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

答案 1 :(得分:1)

从给出的有限症状来看,JTA事务似乎没有被启动和传播。你的EM可以正常工作 - 从数据库读取,允许数据更改它的持久上下文缓存,但从不写入数据库。

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

  

我启用了注释驱动的交易。

确保在Spring配置中配置如下:

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

其中:

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

答案 2 :(得分:1)

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

答案 3 :(得分:1)

以这种方式尝试@Transactional

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

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