Dziwne zachowanie w @Transactional (propagacja = Propagacja.REQUIRES_NEW)
Oto mój problem:
Używam partii na aplikacji Java EE / Spring / Hibernate. Ta partia wywołuje amethod1
. Ta metoda wywołuje amethod2
które mogą rzucaćUserException
(klasa rozszerzającaRuntimeException
). Oto jak to wygląda:
@Transactional
public class BatchService implements IBatchService {
@Transactional(propagation=Propagation.REQUIRES_NEW)
public User method2(User user) {
// Processing, which can throw a RuntimeException
}
public void method1() {
// ...
try {
this.method2(user);
} catch (UserException e) {
// ...
}
// ...
}
}
Wyjątek jest przechwytywany w miarę kontynuowania wykonywania, ale pod koniecmethod1
po zamknięciu transakcji rzucany jest wyjątek RollbackException.
Oto ślad stosu:
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:476)
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.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at $Proxy128.method1(Unknown Source)
at batch.BatchController.method1(BatchController.java:202)
Gdymethod2
nie rzuca tego wyjątku, działa dobrze.
Co próbowałem:
Oprawa@Transactional(noRollbackFor={UserException.class}))
namethod1
Spróbuj złapaćmethod2
Ale nic nie zmieniło.
Ponieważ wyjątek jest zgłaszany w innej transakcji, w której nastąpiło wycofanie, nie rozumiem, dlaczego nie działa. Spojrzałem na to:Jpa transaction javax.persistence.RollbackException: Transakcja oznaczona jako rollbackOnly ale to mi nie pomogło.
Będę bardzo wdzięczny, jeśli ktoś poda mi jakąś wskazówkę.
Aktualizacja
Zrobiłem to, ustawiającpropagation=Propagation.REQUIRES_NEW
o metodzie zwanej przezmethod2
(w rzeczywistości to ten, który wysyła wyjątek). Ta metoda jest zdefiniowana w klasie bardzo podobnej do mojejBatchService
. Więc nie rozumiem, dlaczego działa na tym poziomie, a nie namethod2
.
method2
tak publicznie jak adnotacja@Transactional
nie jest brany pod uwagę, jeśli metoda jest prywatna, jak wspomniano w dokumentacji:Adnotacja @Transactional może być umieszczona przed definicją interfejsu, metodą na interfejsie, definicją klasy lub metodą publiczną w klasie.
Próbowałem również użyćException
zamiastRuntimeException
(jak to jest bardziej odpowiednie), ale nic też nie zmieniło.Nawet jeśli działa, pytanie pozostaje otwarte, ponieważ ma dziwne zachowanie i chciałbym zrozumieć, dlaczego nie działa tak, jak powinno.