У меня есть это странное поведение с транзакциями весной.Сделка отменена предыдущей транзакцией
У меня есть два класса:
класс обслуживания, который первым вызывается doGenericServiceStuff (другим объектом, уже обладают сделки):
@Service("myService")
public class ServiceClass {
public void doGenericServiceStuff(Object someBean){
BusinessI business = BusinessFactory.getBusinessForObject(someBean); //Here, returns the commonBusinessClass bean
business.doGenericBusinessStuff(someBean);
}
/*@Transactional (readOnly=false, rollbackFor=Exception.class, propagation=Propagation.REQUIRES_NEW)*/
public void firstOperation(Object o){
//multiple database insert and stuff
}
/*@Transactional (readOnly=false, rollbackFor=Exception.class, propagation=Propagation.REQUIRES_NEW)*/
public void secondOperation(Object o){
//also multiple database insert and stuff
}
}
Тогда CommonBusinessClass, что вызывает некоторые ServiceClass' методы:
@Bean("commonBusinessClass")
public class CommonBusinessClass implements BusinessI{
@Autowired
@Qualifier("myService")
protected ServiceClass = null;
@Transactional(rollBackFor=Exception.class, Propagation=Propagation.MANDATORY)
public Object doGenericBusinessStuff(Object o){
service.firstOperation(o);
service.secondOpertion(o);
//There can be stuff here in other BusinessClass
return o;
}
}
Отказ от ответственности: Очевидно, что я не манипулируют Objects
, как это, и я не называю моей мето d doGenericStuff()
. Однако ServiceClass действительно вызывает CommonBusinessClass, который, в свою очередь, вызывает ServiceClass. Может быть, это плохой дизайн, может быть, причина в том, что он не работает, но это то, что у меня есть на данный момент.
Методы в ServiceClass
не являются транзакционными (поэтому комментарии), а doGenericBusinessStuff()
(с Propagation.MANDATORY
).
Новое требование заключается в том, что если secondOperation()
не удался (и откаты) firstOperation()
, следует совершить. Поэтому я добавил @Transactional
за firstOperation()
и secondOperation()
(те, о которых идет речь). Я ожидал, что он будет работать нормально (исключение в secondOperation()
не откатывает то, что было сделано в firstOperation()
), но это не так. Однако, если я удалю @Transactional
по адресу doGenericBusinessStuff()
, он работает.
Это поведение нормальное, или есть что-то еще, что приходит в игру в моем реальном приложении, которое я не помещал здесь (потому что я упростил его)? Почему новая транзакция должна быть связана друг с другом каким-либо образом? Какие-нибудь идеи о том, что может случиться?
Заранее спасибо.
Alright, поэтому маркировка и firstOperation как '@ Transactional' с' Propagation.REQUIRES_NEW' не сделать его независимую сделку (что не будет откатить, если 'doGenereicBusinessStuff()' делает)? – Asoub
Если вы используете Propagation.REQUIRES_NEW, то Spring создаст новую независимую транзакцию. http://www.byteslounge.com/tutorials/spring-transaction-propagation-tutorial – reos
Но если все ваши методы находятся в одном классе. doGenericBusinessStuff и firstOperation, то Spring transactional не создаст новую транзакцию. Весна не в состоянии справиться с этим сценарием неявно. Любая аннотация по вызываемому методу будет проигнорирована (поскольку вызов происходит на «этом», а не на прокси-сервере транзакции) Вам нужно переключиться на AspectJ для обработки такого сценария. http://stackoverflow.com/questions/28480480/propagation-requires-new-does-not-create-a-new-transaction-in-spring-with-jpa – reos