2015-11-17 2 views
0

У меня есть две службы. Один загружает данные из БД, изменять их и вызывает другую службу сохраняться измененные данные:Почему новые весенние транзакции создаются при вызове метода другой службы?

@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, если я удаляю строку, помеченную «##», для всего процесса создается только одна транзакция, что позволяет откатить в случае возникновения какого-либо исключения.

  1. Является ли это ожидаемым весенним поведением?
  2. Есть ли способ сохранить транзакцию 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 не в том же проекте. Если я поместил их в один и тот же проект, транзакция будет отброшена назад, когда в процессе произойдет исключение.

+0

вы можете проверить http://stackoverflow.com/questions/6222600/transactional-method-calling- another-method-without-transactional-anotation – Murli

+0

Вы доказали, что ваши транзакционные прокси-серверы на месте? т. е. ваша конфигурация верна? Если вы оставите точку в 'CalledService # presistData (Data)', можете ли вы указать stacktrace в этот момент? Это подтвердит, что ваша проблема заключается в том, что транснациональные прокси-серверы не настраиваются. Тогда вы/мы можем отлаживать это знание. –

+0

Хорошо, мы можем видеть материал Transaction в stacktrace, так что .. вы уверены, что в какой-то момент вы покидаете внешнюю область '@ Transactional', прежде чем вы ожидаете, что данные будут зафиксированы? Вы говорите, что новая транзакция создается каждый раз, когда вызывается CalledService, это неверно, есть одна транзакция, и оба Caller и Called объединяются в одну транзакцию. Поэтому я говорю о выходе из внешней границы @ @ Transactional перед проверкой данных в БД. Для получения новой транзакции см. Поддержку '@Transactional (распространение = Propagation.REQUIRES_NEW)' для внутреннего (CalledService). –

ответ

0

принудительное распространение. ПРЕДУПРЕЖДЕНИЕ для поддержки текущей транзакции вместо создания новой. Удаление аннотации Transactional является плохой практикой, поскольку транзакционное поведение требуется вызывающему, а сам метод потенциально небезопасен.

+0

REQUIRED по умолчанию: https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/transaction/annotation/Transactional.html#propagation-- –

+0

Если вы имеете в виду, указав '@Transactional (распространение = распространение.ТРЕБУЕТСЯ) 'на CalledService, как указано в моем вопросе, я уже пробовал это. –

+0

Я имею в виду транзакционную аннотацию на методы, а не на такие классы, как в вашем сообщении. –

Смежные вопросы