상위 트랜잭션이 롤백 되었기 때문에 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 JTA/JPA CMT 트랜잭션 롤백이 하위 트랜잭션에 영향을 미침
다음 예제는 본질을 보여줍니다. 자체 테네시의 Process EJB는 시작시 감사자를 호출하고 DB 작업을 수행하지만 실패를 결정하고 롤백을 설정 한 다음 완료시 감사자를 호출합니다. 감사 자 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()가 호출 될 때 장애를 결정하고, 세트 롤백까지 조용히 진행한다는 것이다. 이 시점에서 두 번째 감사 호출은 별도의 트랜잭션이 아닌 현재 트랜잭션의 일부인 것처럼 Client의 Transaction Aborted를 발생시킵니다. 또한 첫 번째 감사 호출은 데이터베이스에 데이터를 저장하지 않습니다. 성공하더라도 부모가 커밋 할 때까지 커밋하지 않습니다 (정상입니까?). 이것은 별도의 트랜잭션에서 XA가 아니어야합니다.
트랜잭션이 독립적이라고 주장하는 많은 기사를 읽었지만 this one은 부모가 커밋 할 때까지 중첩 된 트랜잭션이 커밋되지 않으며 부모가 롤백하면 자식도 롤백한다고 제안합니다. 가장 큰 트랜잭션이 커밋 될 때까지 커밋 할 것이 없기 때문에 부분적 또는 상태 작업을 수행하는 방법을 알 수 없습니다.
JPA 구성 - 원래 단일 데이터 소스를 사용했지만 나중에 두 개로 전환되었지만 차이점은 관찰되지 않았습니다. 즉, 롤백이 작동하도록되어 방법 경우
<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이 코드 내의 제어점에 대한 ** 항목을 업로드했습니다.
ADDED :이 second log에는 FINEST에서 EclipseLink 레벨이 있습니다.
편집 : 문제를 일으키는 원인을 정확하게 보여주기 위해 코드를 수정하고 하나의 지속성 관리자 만 반환했습니다.
게시 한 스 니펫이 정확하며 설명 된대로 작동해야합니다. JPA 구성을 제공 할 수 있습니까? (정확한 JTA 구성을 지정했는지 확인하십시오) –
설명대로 작동해야합니다. 동일한 기술을 사용하여 오류를 감사하고 작동했습니다. GF 관리 콘솔에서 tx 관리자 로그를 켜고 어떻게되는지보십시오. – ewernli
답장을 보내 주셔서 감사합니다. 중첩 트랜잭션이 독립적이지 않은지 확인하고 있습니까 (상위 롤백은 하위 롤백을 유발 함)? 이것이 EJB 3.1 스펙의 13.6.2.4와 어떻게 조화를 이루지는 못합니다. JTA/JPA가 중첩 트랜잭션 (플랫 트랜잭션 만)을 지원하지 않지만 아직 존재한다는 것을 계속 읽습니다. –