spring @transactional事務問題及解決
阿新 • • 發佈:2021-01-11
1. 資料庫引擎選擇錯誤
2.@transactional標註的方法 所在的類需要被spring管理 並且方法是public修飾
3. 自呼叫的時候出現的事務失效:
1 @Service 2 public class Service{ 3 4 public void m(){ 5 m1(); 6 m2(); 7 8 } 9 10 @transactional 11 public void m1(){ 12 13 14 } 15 @transactional 16 publicvoid m2(){ 17 18 } 19 }
1 @Service 2 public class DmzService { 3 @Transactional 4 public void save(A a, B b) { 5 saveB(b); 6 } 7 8 @Transactional(propagation = Propagation.REQUIRES_NEW) 9 public void saveB(B b){ 10 dao.saveB(b); 11 } 12}
以上兩種情況皆會導致事務失敗,原因是 自呼叫呼叫的是目標類而不是代理類的方法,所以解決問題的點也在這裡
使用代理類的方法是
1. 自己autowire注入自己
2. 使用aopcontext
@Service public class DmzService { @Transactional public void save(A a, B b) { ((DmzService) AopContext.currentProxy()).saveB(b); } @Transactional(propagation = Propagation.REQUIRES_NEW)public void saveB(B b){ dao.saveB(b); } }
// exposeProxy=true代表將代理類放入到執行緒上下文中,預設是false
@EnableAspectJAutoProxy(exposeProxy = true)
事務回滾問題
1. 想回滾卻提交了
spring預設回滾是發生了error或者RunTimeException 如果想要回滾其他的異常 需要制定rollbackfor
2. 想提交卻回滾了
@Service public class DmzService { @Autowired IndexService indexService; @Transactional public void testRollbackOnly() { try { indexService.a(); } catch (ClassNotFoundException e) { System.out.println("catch"); } } } @Service public class IndexService { @Transactional(rollbackFor = Exception.class) public void a() throws ClassNotFoundException{ // ...... throw new ClassNotFoundException(); } }
以上程式碼會丟擲異常! 原因是 事務巢狀的情況下,當內部事務回滾會把rollbackOnly屬性設定為true 所以會回滾
解決:
1. 如果想內部事務回滾 外部事務繼續執行
將內部事務的傳播級別設定為nested或者requires_new
@Transactional(rollbackFor = Exception.class,propagation = Propagation.NESTED)
2. 想內部事務發生異常 外部事務回滾 整體回滾 不拋異常
@Transactional public void testRollbackOnly() { try { indexService.a(); } catch (ClassNotFoundException e) { // 加上這句程式碼 TransactionInterceptor.currentTransactionStatus().setRollbackOnly(); } }