내 @Transactional 메서드 내에서 트랜잭션을 커밋하는 데 문제가 있습니다.
methodA() {
methodB()
}
@Transactional
methodB() {
...
em.persist();
...
em.flush();
log("OK");
}
methodA ()에서 methodB ()를 호출하면 메서드가 성공적으로 전달되고 로그에 “OK”가 표시됩니다. 하지만 나는
Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Transaction marked as rollbackOnly org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Transaction marked as rollbackOnly
at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:521)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:754)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723)
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:393)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:120)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:622)
at methodA()...
- methodB의 컨텍스트는 예외에서 완전히 누락되어 있습니다.
- methodB () 내의 무언가가 트랜잭션을 롤백으로 만 표시 했습니까? 어떻게 알 수 있습니까? 예를 들어 다음과 같은 것을 확인하는 방법이 있습니까
getCurrentTransaction().isRollbackOnly()?
-이와 같이 방법을 단계별로 수행하고 원인을 찾을 수 있습니다.
답변
당신은 귀하의 방법을 표시하면 @Transactional
, 당신의 방법 내부 예외의 발생은 롤백 전용 (당신이 그들을 잡을 경우에도)로 주변 TX를 표시합니다. @Transactional
주석의 다른 속성을 사용 하여 다음과 같은 롤백을 방지 할 수 있습니다 .
@Transactional(rollbackFor=MyException.class, noRollbackFor=MyException2.class)
답변
마침내 문제를 이해했습니다.
methodA() {
methodB()
}
@Transactional(noRollbackFor = Exception.class)
methodB() {
...
try {
methodC()
} catch (...) {...}
log("OK");
}
@Transactional
methodC() {
throw new ...();
}
무슨 일이 일어나는 methodB
가는에 올바른 주석이 있어도 methodC
그렇지 않다는 것입니다. 예외가 발생하면 두 번째 @Transactional
는 첫 번째 트랜잭션을 어쨌든 롤백으로 만 표시합니다.
답변
다시 코딩하거나 다시 빌드 할 필요없이 원인이되는 예외를 빠르게 가져 오려면 중단 점을
org.hibernate.ejb.TransactionImpl.setRollbackOnly() // Hibernate < 4.3, or
org.hibernate.jpa.internal.TransactionImpl() // as of Hibernate 4.3
스택에서 보통 인터셉터로 올라갑니다. 거기에서 일부 catch 블록에서 발생하는 예외를 읽을 수 있습니다.
답변
내 응용 프로그램을 실행하는 동안이 예외로 고생했습니다.
마지막으로 문제는 SQL 쿼리에있었습니다. 있었습니다. 나는 쿼리가 잘못되었음을 의미합니다.
쿼리를 확인하십시오. 이것은 내 제안입니다
답변
던져지고 잡히는 예외를 찾으십시오. ...
코드 섹션 . 런타임 및 롤백 애플리케이션 예외로 인해 다른 장소에서 발견 된 경우에도 비즈니스 메소드에서 폐기 될 때 롤백이 발생합니다.
컨텍스트를 사용하여 트랜잭션이 롤백으로 표시되었는지 여부를 확인할 수 있습니다.
@Resource
private SessionContext context;
context.getRollbackOnly();
답변
솔루션으로 좋은 설명을 찾았습니다 : https://vcfvct.wordpress.com/2016/12/15/spring-nested-transactional-rollback-only/
1) 실제로 트랜잭션 제어가 필요하지 않은 경우 중첩 된 메서드에서 @Transacional을 제거합니다. 따라서 예외가 있어도 거품이 발생하고 트랜잭션에 영향을 미치지 않습니다.
또는:
2) 중첩 된 메서드에 트랜잭션 제어가 필요한 경우 전파 정책에 대해 REQUIRE_NEW로 설정하여 예외를 throw하고 롤백 전용으로 표시하더라도 호출자에게 영향을주지 않습니다.
답변
Bean.xml에서 transactionmanager를 비활성화하십시오.
<tx:annotation-driven proxy-target-class="true" transaction-manager="transactionManager"/>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
이 줄을 주석 처리하면 롤백을 유발하는 예외가 표시됩니다.)