spring boot -- 事務
事務
基礎
分為 編程式事務 與 聲明式事務
import org.springframework.transaction.annotation
@Transactional() @Transactional
在service層使用@Transcational
@Transactional使用在類上表示類中的方法都是事務
一般在使用單元測試時,都會添加@Rollback來進行數據的回滾
@EnableTransactionManagement (@SpringBootApplication)
JPA默認開啟transactional,且查詢都為readOnly=true,可以看源碼SimpleJpaRepository
spring boot專門配置事務的類為: org.springframework.boot.autoconfigure.transaction.TransactionalAutoConfiguration,
但是因為在TransactionManagerAutoConfiguration中開啟了對聲明式事務的支持
@ConditionalOnMissingBean
@Configuration
@EnableTransactionManagement
所以在Spring Boot中,不需要顯示聲明
在Spring Boot中,當我們使用了spring-boot-starter-jdbc或spring-boot-starter-data-jpa依賴的時候,框 架會自動默認分別註入DataSourceTransactionManager或JpaTransactionManager。所以我們不需要任何額外 配置就可以用@Transactional註解進行事務的使用。
問題
- 事務不回滾
a) 啟動代理模式
b) shiro導致SpringBoot事務不起效
原因:shiro在啟動配置時Spring還沒有啟動
解決方法:把原來在ShiroConfig裏面初始化的getUserRealm與securityManager方法移動到一個新建的Spring監聽器中進行初始化
c) 默認情況下,只對unchecked異常進行事務回滾,如果是checked異常,則不回滾
unchecked:派生於Error,RuntimeException(如空指針,1/0) 空指針,文件讀寫
checked: 其他的繼承自java.lang.Exception的異常,如IOException,TimeOutException
解決方法: 對於checked異常不回滾的 增加註解
@Transaction(rollbackFor=Exception.class)
如果異常被try{} catch{}到,事務不會回滾
使用回滾需要拋出異常 try{} catch{throw new RuntimeException}
d) 數據庫需要支持回滾
Innodb 與 myisam的區別
e) 是否開啟對註解的解析
@EnableTransactionManagement
f) spring是否掃描到該包
g) 是否是方法的調用
使用代理模式,controller調用service的代理,進行操作
@Component public class TransactionConfig { @Autowired PlatformTransactionManager transactionManager; //獲取配置器 public DeafultPointerAdvisor getAdvisor(){ //聲明切點 AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut(); cut.setExpression("excution()"); //切點表達式 DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(); advisor.setPointcut(pointcut); //放入切點 Properties attributes = new Properties(); //properties是一種容器 //get* 以get開頭的函數 //PROPAGATIO_REQUIRED 如果是事務,則進行;不是事務,作為事務 //-Exception 異常回滾 attribute.setProperty("get*","PROPAGATIO_REQUIRED,readOnly,-Exception"); //transactionManager spring自動生成 TransactionInterceptor txAdvice = new TransactionInterceptor(transactionManager,attributes); advisor.setAdvice(txAdvice); return advisor; } }
@Autowired TransactionConfig transactionConfig; //定義代理類 public <T> T getObj(Object object){ ProxyFactoryBean factory = new ProxyFactoryBean(); factory.setTarget(object); factory.addAdvisor(transactionConfig.getAdvisor()); T tObject = (T)factory.getObject(); return tObject }
spring boot -- 事務