我正在使用Oracle数据库运行Glassfish 3.1.1,并且遇到了一个问题,即事务处理没有回滚,但到目前为止只在一个特定的环境中运行。相同的应用程序在其他计算机上按预期工作。但是,同一台计算机上的两个单独的Glassfish域受到影响。
在受影响的环境中,我在EJB中抛出RuntimeException的容器管理事务(CMT)和使用UserTransaction#rollback()
的bean管理事务(BMT)都有类似的结果。
在这两种情况下,基本问题似乎是JDBC连接仍以某种方式设置为autoCommit = true,即使正在进行JTA事务。
我的EJB / CMT测试如下所示:
@Named
@Stateless
public class TransactionTest {
@PersistenceContext
EntityManager entityManager;
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void rollbackTest() {
Foo foo = new Foo();
entityManager.persist(foo);
entityManager.flush();
throw new RuntimeException("should be rolled back");
}
}
我的BMT / UserTransaction测试是这样的:
public void rollbackUtxTest() throws Exception {
utx.begin();
Foo foo = new Foo();
entityManager.persist(foo);
entityManager.flush();
utx.rollback();
}
当我调用任一方法时,即使事务已回滚,也会提交INSERT INTO FOO
。
我缺少什么 - 也许我没有连接池/数据源没有设置正确?
我正在使用OracleConnectionPoolDataSource作为数据源类名。我需要做些什么来确保我的数据库连接参与JTA事务吗?
更新1 我原本认为这是OracleConnectionPoolDataSource
的一个问题,但事实证明它没有相关性。相同的池配置适用于一个环境,但不适用于另一个环境。
更新2 澄清这不是特定的EJB / CMT问题,而是一般的JTA问题。
更新3 添加了有关JDBC自动提交的信息。确认persistence.xml是正确的。
答案 0 :(得分:3)
看起来这可能是domain.xml的问题,可能是Glassfish错误。
在persistence.xml中,我有
<jta-data-source>jdbc/TEST</jta-data-source>
。
在domain.xml中,我有
<jdbc-resource pool-name="TEST_POOL" description="" jndi-name="jdbc/TEST"></jdbc-resource>
但没有相应的<resource-ref ref="jdbc/TEST">
- 丢失或拼写错误。 (我相信我最后通过UI创建JNDI数据源,意识到名称错误,然后手动修复域jdbc-resource
中的JNDI名称,但没有在resource-ref
中修复它。
在这种情况下,我注入的EntityManager
仍然有效,但没有参与JTA事务。如果我修复了domain.xml,它会按预期工作。
答案 1 :(得分:0)
您没有在EJBException中包装您的Exception。