У меня есть две службы. Один загружает данные из БД, изменять их и вызывает другую службу сохраняться измененные данные:Почему новые весенние транзакции создаются при вызове метода другой службы?
@Service
@Transactional
public class CallerService {
public void doSomething() {
List dataList = loadData();
for(data : dataList) {
data.setValue("newValue");
calledService.persistData(data);
}
}
}
@Service
@Transactional //##
public class CalledService {
public void persistData(Data data){
myDao.persistData(data);
}
}
С таким кодом, новая транзакция создается каждый раз, когда CalledService.persistData называется. Howether, если я удаляю строку, помеченную «##», для всего процесса создается только одна транзакция, что позволяет откатить в случае возникновения какого-либо исключения.
- Является ли это ожидаемым весенним поведением?
- Есть ли способ сохранить транзакцию CalledService и избежать создания новых транзакций при переходе из CallerService в CalledService?
Обратите внимание, что я попытался изменить распространение на «Обязательно» и несколько других значений в CalledService.
EDIT: Вот StackTrace из persistData:
CalledServiceImpl.persistData(Reglement, int, Gestionnaire) line: 304
NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]
NativeMethodAccessorImpl.invoke(Object, Object[]) line: 57
DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43
Method.invoke(Object, Object...) line: 606
AopUtils.invokeJoinpointUsingReflection(Object, Method, Object[]) line: 317
ReflectiveMethodInvocation.invokeJoinpoint() line: 190
ReflectiveMethodInvocation.proceed() line: 157
TransactionInterceptor$1.proceedWithInvocation() line: 99
TransactionInterceptor(TransactionAspectSupport).invokeWithinTransaction(Method, Class<?>, InvocationCallback) line: 281
TransactionInterceptor.invoke(MethodInvocation) line: 96
ReflectiveMethodInvocation.proceed() line: 179
JdkDynamicAopProxy.invoke(Object, Method, Object[]) line: 207
$Proxy51.persistData(Data) line: not available
CallerServiceImpl.doSomething(String) line: 277
CallerServiceImpl.runBatch(String[]) line: 178
CallerServiceImpl(BatchAbstractService).doBatch(String[]) line: 29
NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]
NativeMethodAccessorImpl.invoke(Object, Object[]) line: 57
DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43
Method.invoke(Object, Object...) line: 606
AopUtils.invokeJoinpointUsingReflection(Object, Method, Object[]) line: 317
JdkDynamicAopProxy.invoke(Object, Method, Object[]) line: 201
$Proxy95.doBatch(String[]) line: not available
ClientBatch.process(String, String[]) line: 78
ClientBatch.main(String[]) line: 53
EDIT2: CallerService и CalledService не в том же проекте. Если я поместил их в один и тот же проект, транзакция будет отброшена назад, когда в процессе произойдет исключение.
вы можете проверить http://stackoverflow.com/questions/6222600/transactional-method-calling- another-method-without-transactional-anotation – Murli
Вы доказали, что ваши транзакционные прокси-серверы на месте? т. е. ваша конфигурация верна? Если вы оставите точку в 'CalledService # presistData (Data)', можете ли вы указать stacktrace в этот момент? Это подтвердит, что ваша проблема заключается в том, что транснациональные прокси-серверы не настраиваются. Тогда вы/мы можем отлаживать это знание. –
Хорошо, мы можем видеть материал Transaction в stacktrace, так что .. вы уверены, что в какой-то момент вы покидаете внешнюю область '@ Transactional', прежде чем вы ожидаете, что данные будут зафиксированы? Вы говорите, что новая транзакция создается каждый раз, когда вызывается CalledService, это неверно, есть одна транзакция, и оба Caller и Called объединяются в одну транзакцию. Поэтому я говорю о выходе из внешней границы @ @ Transactional перед проверкой данных в БД. Для получения новой транзакции см. Поддержку '@Transactional (распространение = Propagation.REQUIRES_NEW)' для внутреннего (CalledService). –