我需要一些幫助,試圖調試爲什麼我的春季啓動應用程序的事務管理不起作用。@事務註釋不按預期工作
基本思想是我有2個表,我想寫一些東西。當兩個表中的一個發生任何錯誤時,事務應該被回滾並且不應該寫入數據庫。
下面是代碼的簡化版本:
@Transactional
public void archiveTask(String taskId) {
OffloadedRun run = new OffloadedRun();
run.setStartDateTime(LocalDateTime.now());
calculationRunRepository.save(run);
List<SingleContractCalculationResults> activeResults = contractCalculationResultAccessService.get(taskId);
for (SingleContractCalculationResults result : example) {
for (Map.Entry<String, ContractResults> entry : result.getResultsPerScenario().entrySet()) {
String scenario = entry.getKey();
ContractResults results = entry.getValue();
OffloadedCalculationResult offloadedCalculationResult = new OffloadedCalculationResult();
// offloadedCalculationResult.setOffloadedRun(run);
offloadedCalculationResult.setContractId(result.getContractId());
calculationResultRepository.save(offloadedCalculationResult);
}
}
}
我執行的保存方法的類是被這樣定義彈簧數據JPA庫:
public interface CalculationRunRepository extends JpaRepository<OffloadedRun, String> {
}
的線I註釋掉是強制性列。我這樣做是爲了強制執行ConstraintViolationException來測試在第二個表中保存某些內容時發生的異常。
會發生什麼是第一個實體保存成功,應該不會發生。我想弄明白爲什麼。
我的彈簧引導應用程序配置爲@EnableTransactionManagement
以在我自己的服務中啓用@Transactional
註釋(如此圖所示)。
我改變的日誌記錄級別org.springframework.transaction.interceptor
來跟蹤,看看發生了什麼事情:
o.s.t.i.TransactionInterceptor : Getting transaction for [be.sodemo.calculator.offloading.TaskArchiverImpl.archiveTask]
o.s.t.i.TransactionInterceptor : Getting transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
o.s.t.i.TransactionInterceptor : Completing transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
o.s.t.i.TransactionInterceptor : Getting transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
o.s.t.i.TransactionInterceptor : Completing transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
o.s.t.i.TransactionInterceptor : Getting transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
o.s.t.i.TransactionInterceptor : Completing transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
o.s.t.i.TransactionInterceptor : Getting transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
o.s.t.i.TransactionInterceptor : Completing transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
o.s.t.i.TransactionInterceptor : Getting transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
o.s.t.i.TransactionInterceptor : Completing transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
o.s.t.i.TransactionInterceptor : Completing transaction for [be.sodemo.calculator.offloading.TaskArchiverImpl.archiveTask]
o.h.e.j.s.SqlExceptionHelper : SQL Error: 1048, SQLState: 23000
o.h.e.j.s.SqlExceptionHelper : Column 'run_id' cannot be null
o.h.e.j.b.i.AbstractBatchImpl : HHH000010: On release of batch it still contained JDBC statements
o.a.c.c.C.[.[.[.[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement] with root cause
com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Column 'run_id' cannot be null
at sun.reflect.GeneratedConstructorAccessor2599.newInstance(Unknown Source) ~[?:?]
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java) ~[?:1.8.0_102]
at java.lang.reflect.Constructor.newInstance(Constructor.java:423) ~[?:1.8.0_102]
at com.mysql.jdbc.Util.handleNewInstance(Util.java:425) ~[mysql-connector-java-5.1.40.jar:5.1.40]
這
後,我不知道該記錄將是什麼樣子,如果交易管理工作正常,但它看起來它正在完成每筆交易。
有沒有人有一個想法,我可以嘗試接下來看看發生了什麼問題?
編輯:直到現在我一直在使用MySQL數據庫。我注意到,當我在H2數據庫上測試完全相同的代碼時,似乎回滾按預期工作。我看到的唯一區別是它引發了另一個特定於供應商的異常。
我試過明確設置上@Transactional註釋中的rollbackFor屬性,像這樣:
@Transactional(rollbackFor = {Exception.class, MySQLIntegrityConstraintViolationException.class})
但即使這樣,也沒有引起回滾。
編輯:
這些都與JPA /休眠我的春天啓動設置:
spring:
jpa:
hibernate:
ddl-auto: none
dialect: org.hibernate.dialect.MySQL5Dialect
database: mysql
properties:
hibernate:
order_inserts: true
jdbc:
batch_size: 50
datasource:
url: jdbc:mysql://localhost/local-test-db
driver-class-name: com.mysql.jdbc.Driver
請問您可以檢查'@ Transactional'註解的導入嗎?確保它不是從javax包中導入的,而是從spring包中導入的。 – galovics
這是註釋的春天版本:org.springframework.transaction.annotation.Transactional – geoffreydv
請問您可以包含'calculationRunRepository.save(run)'方法嗎?這可能是因爲你在這裏有不同的事務傳播。 – galovics