java - EJB JTA/JPA CMT 事务回滚影响子事务

标签 java jpa glassfish ejb

我在事务回滚方面遇到问题,其中一个用 REQUIRES_NEW 注释的子事务被回滚,因为父事务被回滚。我很困惑,因为我曾认为 JTA/JPA 独立处理这些事务,因此一个事务的回滚不会影响另一个事务。我正在使用 Java 1.6.0_24、EJB 3.1、GlassFish 3.0.1、JPA 2、MS SQL Server(非 XA)2008、CMT。

下面的示例显示了本质:进程 EJB 在其自己的 TN 中在开始时调用审计器,执行 DB 操作但确定失败,设置回滚,然后在完成时调用审计器。 Auditor EJB 调用 JPA 以在单独的事务 (REQUIRES_NEW) 中创建审计记录,并且在事务成功时工作正常。该代码显示了一个通用的审计结构,省略了所有不必要的代码——泛型似乎是问题的一部分。

public interface ErrorDescriptor {  
    public String getName ();  
}  

public interface GenericAuditor<T extends ErrorDescriptor> {
    public void log(T errorType);
}

public abstract class AbstractGenericAuditorImpl<T extends ErrorDescriptor>
    implements GenericAuditor<T> {
}

public enum AuditType implements ErrorDescriptor {
   BEGIN, FAILED;
    public String getName() { return name(); }
}

public interface Auditor extends GenericAuditor<AuditType> {
    // The absence of the following 2 lines causes the problem
    @Override
    public void log(AuditType errorType);
}

@Stateless
public class AuditorImpl
    extends AbstractGenericAuditorImpl<AuditType>
    implements Auditor {
    @PersistenceContext ("EntityPersistenceManagement")
    protected EntityManager entityManager;

    @Override
    @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
    public void log (AuditType e) {
        ErrorEvent errorEvent = new ErrorEvent (); // entity
        errorEvent.setName (e.getName());
        entityManager.persist (errorEvent);
   }
}

@Stateless
public class ProcessImpl implements Process {
    @Resource private EJBContext ejbContext;
    @EJB private Auditor auditor;

@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void method1() {
    auditor.log(AuditType.BEGIN);

    // Perform series of actions including database ops
    // Takes up to 1 minute
    // Somethings happen that detects failure
    ejbContext.setRollbackOnly ();

    auditor.log(AuditType.FAILED);
}
}

问题是当 parent.method1() 被调用时,它会安静地进行,直到它确定失败并设置回滚。那时,第二次审计调用抛出客户的交易已中止,就好像它是当前交易的一部分而不是在单独的交易中一样。此外,第一个审计调用不会在数据库中放置任何数据——即使成功它也不会提交,直到父项提交(这正常吗?)这在单独的事务中应该是非 XA。

我读过许多声称交易是独立的文章,但是 this one建议嵌套事务在父事务提交之前不提交,如果父事务回滚,子事务也会回滚。如果那是真的,我不明白如何提交部分或状态工作,因为在提交最顶层的事务之前什么都不会提交。

JPA Config--我最初使用单个数据源,但后来切换到两个,但我没有发现任何差异。

<persistence-unit name="EntityPersistenceManagement" transaction-type="JTA">
<jta-data-source>jdbc/app1</jta-data-source>
<properties>
    <property name="eclipselink.logging.level" value="INFO"/>
    <property name="eclipselink.weaving.internal" value="false"/>
    <property name="eclipselink.weaving" value="false"/>
    <property name="eclipselink.weaving.fetchgroups" value="false"/>
    <property name="eclipselink.weaving.changetracking" value="false"/>
    <property name="eclipselink.weaving.lazy" value="false"/>
    <property name="eclipselink.weaving.internal" value="false"/>
    <property name="eclipselink.weaving.eager" value="false"/>

    <property name="eclipselink.cache.shared.default" value="false"/>
    <property name="eclipselink.cache.shared" value = "false"/>
    <property name="eclipselink.query-results-cache" value="false"/>

    <property name="hibernate.dialect" value="org.hibernate.dialect.SQLServerDialect"/>
</properties>

<exclude-unlisted-classes>true</exclude-unlisted-classes>
<class>org.foo.entities.AppRecord</class>
<class>org.foo.entities.ErrorEvent</class>

谁能说回滚是否应该这样工作?也许这在 XA 下有所不同?

我已经上传了这个annotated transaction log在代码中查找控制点的 ** 条目。

已添加:这 second log具有 FINEST 级别的 EclipseLink。

编辑:我修改了代码以准确显示导致问题的原因并仅返回给一个持久性管理器。

最佳答案

此问题是 GlassFish 的错误 https://java.net/jira/browse/GLASSFISH-8319 ,在 v 3.1 中记录为已解决。

关于java - EJB JTA/JPA CMT 事务回滚影响子事务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17280724/

相关文章:

java - 实体扫描在 JPA/hibernate/spring 应用程序中不起作用

java - 如何删除 URL 中的 Java 项目名称

java - 如何避免在 Activity 更改时杀死并重新启动 firestore 监听器?

java - 从需要代码修复的日期添加/删除天数

java - Oracle 数据源连接池不适用于 Spring 和 JDBCTemplate

java - 从位于资源 glassfish java 中的文件读取

netbeans - Netbeans 创建 Glassfish 域的管理员用户和密码?

java - 使用正则表达式更新保留字(有异常(exception))

oracle - Hibernate 5 序列生成问题

postgresql - javax.persistence.NoResultException : No entity found for query JPQL Query