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