javascript
Spring 之注解事务 @Transactional
前些天發(fā)現了一個巨牛的人工智能學習網站,通俗易懂,風趣幽默,忍不住分享一下給大家。點擊跳轉到教程。
先讓我們看代碼吧!
以下代碼為在“Spring3事務管理——基于tx/aop命名空間的配置”基礎上修改。首先修改applicationContext.xml如下:
| ? [html]?view plain?copy 實現類代碼: |
?
?| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | @Transactional publicclassUserScoreRepositoryImpl?implementsUserScoreRepository { ????privateJdbcTemplate jdbcTemplate; ????@Override ????publicUserScore getUserSocore(String userNo) { ????finalUserScore us =?newUserScore(); ????... ????returnus; ????} ????... } |
OK了!以上就實現了簡單的事務管理了。現在再稍微了解下@Transactional。
在配置文件中,默認情況下,<tx:annotation-driven>會自動使用名稱為transactionManager的事務管理器。所以,如果定義的事務管理器名稱為transactionManager,那么就可以直接使用<tx:annotation-driven/>。如下:
| 1 2 3 4 5 6 7 8 | <!-- 配置事務管理器 --> <beanid="transactionManager" ????class="org.springframework.jdbc.datasource.DataSourceTransactionManager" ????p:dataSource-ref="dataSource"> </bean> <!-- enables scanning for @Transactional annotations --> <tx:annotation-driven/> |
<tx:annotation-driven>一共有四個屬性如下,
- mode:指定Spring事務管理框架創(chuàng)建通知bean的方式。可用的值有proxy和aspectj。前者是默認值,表示通知對象是個JDK代理;后者表示Spring AOP會使用AspectJ創(chuàng)建代理?
- proxy-target-class:如果為true,Spring將創(chuàng)建子類來代理業(yè)務類;如果為false,則使用基于接口的代理。(如果使用子類代理,需要在類路徑中添加CGLib.jar類庫)?
- order:如果業(yè)務類除事務切面外,還需要織入其他的切面,通過該屬性可以控制事務切面在目標連接點的織入順序。?
- transaction-manager:指定到現有的PlatformTransaction Manager bean的引用,通知會使用該引用?
?@Transactional的屬性
| 屬性名? | 類型? | 說明? |
| isolation? | 枚舉org.springframework.transaction.annotation.Isolation的值? | 事務隔離級別? |
| noRollbackFor? | Class<? extends Throwable>[]? | 一組異常類,遇到時不回滾。默認為{} |
| noRollbackForClassName? | Stirng[]? | 一組異常類名,遇到時不回滾,默認為{} |
| propagation? | 枚舉org.springframework.transaction.annotation.Propagation的值? | 事務傳播行為? |
| readOnly? | boolean? | 事務讀寫性? |
| rollbackFor? | Class<? extends Throwable>[]? | 一組異常類,遇到時回滾? |
| rollbackForClassName? | Stirng[]? | 一組異常類名,遇到時回滾? |
| timeout? | int? | 超時時間,以秒為單位? |
| value? | String? | 可選的限定描述符,指定使用的事務管理器? |
@Transactional標注的位置
@Transactional注解可以標注在類和方法上,也可以標注在定義的接口和接口方法上。
如果我們在接口上標注@Transactional注解,會留下這樣的隱患:因為注解不能被繼承,所以業(yè)務接口中標注的@Transactional注解不會被業(yè)務實現類繼承。所以可能會出現不啟動事務的情況。所以,Spring建議我們將@Transaction注解在實現類上。
在方法上的@Transactional注解會覆蓋掉類上的@Transactional。
使用不同的事務管理器
如果我們要程序中使用多個事務管理器(主要是針對多數據源的情況),可以通過以下的方式實現:
Service代碼:
| 1 2 3 4 5 6 7 8 9 10 11 | publicclassMultiTxService { ????@Transactional("tran_1") ????publicvoidaddTest(intid){ ????????? ????} ????@Transactional("tran_2") ????publicvoiddeleteTest(intid){ ????????? ????} } |
applicationContext.xml配置如下:?
?| 1 2 3 4 5 6 7 8 9 10 | <beanid="tran_1" ????class="org.springframework.jdbc.datasource.DataSourceTransactionManager" ????p:dataSource-ref="dataSource"> ????<qualifiervalue="tran_1"/> </bean> <beanid="tran_2" ????class="org.springframework.jdbc.datasource.DataSourceTransactionManager" ????p:dataSource-ref="dataSource"> ????<qualifiervalue="tran_2"/> </bean> |
經過以上的代碼,每個事務都會綁定各自的獨立的數據源,進行各自的事務管理。我們可以優(yōu)化下以上代碼,可以自定義一個綁定到特定事務管理器的注解,然后直接使用這個自定義的注解進行標識:
?
?| 1 2 3 4 5 6 | @Target({ElementType.METHOD,ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Transactional("tran_1") public@interfaceCustomerTransactional { } |
在Service代碼中使用:
?| 1 2 3 4 5 6 7 | ... //使用名為tran_1的事務管理器 @CustomerTransactional public void addTest(String str){ ????? } … Spring在TransactionDefinition接口中規(guī)定了7種類型的事務傳播行為, 它們規(guī)定了事務方法和事務方法發(fā)生嵌套調用時事務如何進行傳播: 事務傳播行為類型
? ? spring 事務注解默認遇到throw new RuntimeException("...");會回滾 需要捕獲的throw new Exception("...");不會回滾// 指定回滾 @Transactional(rollbackFor=Exception.class) public void methodName() {// 不會回滾throw new Exception("...");} //指定不回滾 @Transactional(noRollbackFor=Exception.class)public ItimDaoImpl getItemDaoImpl() {// 會回滾throw new RuntimeException("注釋");} // 如果有事務,那么加入事務,沒有的話新建一個(不寫的情況下)@Transactional(propagation=Propagation.REQUIRED) // 容器不為這個方法開啟事務@Transactional(propagation=Propagation.NOT_SUPPORTED)// 不管是否存在事務,都創(chuàng)建一個新的事務,原來的掛起,新的執(zhí)行完畢,繼續(xù)執(zhí)行老的事務@Transactional(propagation=Propagation.REQUIRES_NEW) // 必須在一個已有的事務中執(zhí)行,否則拋出異常@Transactional(propagation=Propagation.MANDATORY)// 必須在一個沒有的事務中執(zhí)行,否則拋出異常(與Propagation.MANDATORY相反)@Transactional(propagation=Propagation.NEVER) // 如果其他bean調用這個方法,在其他bean中聲明事務,那就用事務.如果其他bean沒有聲明事務,那就不用事務.@Transactional(propagation=Propagation.SUPPORTS) /*public void methodName(){// 本類的修改方法 1update();// 調用其他類的修改方法otherBean.update();// 本類的修改方法 2update();}other失敗了不會影響 本類的修改提交成功本類update的失敗,other也失敗*/ @Transactional(propagation=Propagation.NESTED) // readOnly=true只讀,能插入,但不能更新,刪除 @Transactional (propagation = Propagation.REQUIRED,readOnly=true) // 設置超時時間 @Transactional (propagation = Propagation.REQUIRED,timeout=30) // 設置數據庫隔離級別 @Transactional (propagation = Propagation.REQUIRED,isolation=Isolation.DEFAULT) |
?
總結
以上是生活随笔為你收集整理的Spring 之注解事务 @Transactional的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 高性能Javascript 分割任务学习
- 下一篇: 用gson得JSON,数值变为doubl