JPA2:不能通过EJB注入创建的EntityManager仍然可以使用JTA事务

时间:2014-02-22 23:18:27

标签: ejb-3.1 entitymanager jta

我有以下内容:

JAR模块,包含如下所示的DAO类:

public class WhateverDao {

    @PersistenceContext(name="pu")
    EntityManager entityManager;

public Whatever saveOrUpdate(Whatever entity) {
    //entityManager.joinTransaction();
    return entityManager.merge(entity);
}

jar还包含一个像这样的persistence.xml:

<persistence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
    version="2.0" xmlns="http://java.sun.com/xml/ns/persistence">
    <persistence-unit name="pu" transaction-type="JTA">
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
        <jta-data-source>jdbc/jee6Test_mysql_datasource</jta-data-source>
        <!-- Entities classes declared here -->
        <properties>
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />
            <property name="hibernate.hbm2ddl.auto" value="update" />
            <property name="hibernate.transaction.factory_class" value="org.hibernate.transaction.JTATransactionFactory"/>
        </properties>       
    </persistence-unit>
</persistence>

和一个空的beans.xml文件。

此jar用于Web应用程序(WAR文件)中,其中DAO被注入无状态EJB,如下所示:

@Stateless
@LocalBean
public class WhateverEJBImpl {

    @Inject
    private WhateverDao whateverDao;

    public void saveWhatever(Whatever whatever) throws IOException {
        whateverDao.saveOrUpdate(whatever); 
    }

我的问题基本上是我无法让这段代码在数据库中实际存在某些东西。据我了解:

  • 我的EntityManager应该是“容器管理”(由于我在persistence.xml中如何配置它,以及我通过@PersistenceContext注释获取它的事实,最后也是因为jar是部署的WAR文件的一部分在JBOSS EAP 6.2中 - 也尝试使用WebLogic 12c)。
  • 我通过无状态EJB调用它意味着,默认情况下,已经有可用的事务,因此我无需手动管理它

但是,使用上述示例并不会将任何数据持久保存到db(在调用EJB saveWhatever方法时)。

我也尝试过尝试过:

  • 在调用entityManager.joinTransaction()之前调用entityManager.merge(...)(DAO代码段中的注释行)。这给出了错误:

    javax.ejb.EJBException:javax.persistence.TransactionRequiredException:joinTransaction调用上没有活动的JTA事务

  • 手动调用entityManager.getTransaction().begin()commit()entityManager.merge(...)之前和之后。这会出错:

    javax.ejb.EJBException:java.lang.IllegalStateException:JTA EntityManager无法使用getTransaction()

所以,我的问题是,请:我如何:

  • 这样我就可以在一个单独的JAR中有一个单独的DAO类,它使用EntityManager而无需以编程方式(手动)处理事务
  • 将这个包含DAO类的jar集成到一个使用EJB的WebApplication中,以便我可以利用JTA并让它自动管理我的事务(更重要的是,我希望无状态EJB承诺行为,其中JTA负责为每个EJB的方法调用创建事务)

1 个答案:

答案 0 :(得分:0)

好吧,对于其他遇到这种情况的人来说:如果你认为所有东西都是用你的EJB和JTA正确设置的,但JTA事务仍然不能正常工作,(无声地失败等等),这就是我解决它的方法:

我改变了这个持久性单元:

    <!-- bad persistence.xml, JTA transactions don't work -->
<persistence-unit name="pu" transaction-type="JTA">
    <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
    <jta-data-source>jdbc/jee6Test_mysql_datasource</jta-data-source>
    <!-- <class> tags go here -->
    <properties>
        <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />
        <property name="hibernate.hbm2ddl.auto" value="update" />
        <property name="hibernate.transaction.factory_class" value="org.hibernate.transaction.JTATransactionFactory"/>
    </properties>       
</persistence-unit>

对此:

<!-- good persistence.xml, JTA transactions work -->
<persistence-unit name="pu" transaction-type="JTA">
        <provider>org.hibernate.ejb.HibernatePersistence</provider> <!-- note change here ->
        <jta-data-source>jdbc/jee6Test_mysql_datasource</jta-data-source>
        <!-- <class> tags go here -->
        <properties>
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />
            <property name="hibernate.hbm2ddl.auto" value="update" />
                    <!-- and removal of <property> here -->
        </properties>       
    </persistence-unit>