前些天發現了一個巨牛的人工智能學習網站,通俗易懂,風趣幽默,忍不住分享一下給大家。點擊跳轉到教程。
先讓我們看代碼吧!
以下代碼為在“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 public class UserScoreRepositoryImpl? implements UserScoreRepository { ???? private JdbcTemplate jdbcTemplate; ???? @Override ???? public UserScore getUserSocore(String userNo) { ???? final UserScore us =? new UserScore(); ???? ... ???? return us; ???? } ???? ... } |
OK了!以上就實現了簡單的事務管理了。現在再稍微了解下@Transactional。
在配置文件中,默認情況下,<tx:annotation-driven>會自動使用名稱為transactionManager的事務管理器。所以,如果定義的事務管理器名稱為transactionManager,那么就可以直接使用<tx:annotation-driven/>。如下:
1 2 3 4 5 6 7 8 | <!-- 配置事務管理器 --> < bean id = "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事務管理框架創建通知bean的方式。可用的值有proxy和aspectj。前者是默認值,表示通知對象是個JDK代理;后者表示Spring AOP會使用AspectJ創建代理?
- proxy-target-class:如果為true,Spring將創建子類來代理業務類;如果為false,則使用基于接口的代理。(如果使用子類代理,需要在類路徑中添加CGLib.jar類庫)?
- order:如果業務類除事務切面外,還需要織入其他的切面,通過該屬性可以控制事務切面在目標連接點的織入順序。?
- 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注解,會留下這樣的隱患:因為注解不能被繼承,所以業務接口中標注的@Transactional注解不會被業務實現類繼承。所以可能會出現不啟動事務的情況。所以,Spring建議我們將@Transaction注解在實現類上。
在方法上的@Transactional注解會覆蓋掉類上的@Transactional。
使用不同的事務管理器
如果我們要程序中使用多個事務管理器(主要是針對多數據源的情況),可以通過以下的方式實現:
Service代碼:
1 2 3 4 5 6 7 8 9 10 11 | public class MultiTxService { ???? @Transactional ( "tran_1" ) ???? public void addTest( int id){ ???????? ????? } ???? @Transactional ( "tran_2" ) ???? public void deleteTest( int id){ ???????? ????? } } |
applicationContext.xml配置如下:?
1 2 3 4 5 6 7 8 9 10 | < bean id = "tran_1" ???? class = "org.springframework.jdbc.datasource.DataSourceTransactionManager" ???? p:dataSource-ref = "dataSource" > ???? < qualifier value = "tran_1" /> </ bean > < bean id = "tran_2" ???? class = "org.springframework.jdbc.datasource.DataSourceTransactionManager" ???? p:dataSource-ref = "dataSource" > ???? < qualifier value = "tran_2" /> </ bean > |
經過以上的代碼,每個事務都會綁定各自的獨立的數據源,進行各自的事務管理。我們可以優化下以上代碼,可以自定義一個綁定到特定事務管理器的注解,然后直接使用這個自定義的注解進行標識:
?
1 2 3 4 5 6 | @Target ({ElementType.METHOD,ElementType.TYPE}) @Retention (RetentionPolicy.RUNTIME) @Transactional ( "tran_1" ) public @interface CustomerTransactional { } |
在Service代碼中使用:
1 2 3 4 5 6 7 | ... //使用名為tran_1的事務管理器 @CustomerTransactional public void addTest(String str){ ???? ?} … Spring在TransactionDefinition接口中規定了7種類型的事務傳播行為, 它們規定了事務方法和事務方法發生嵌套調用時事務如何進行傳播: 事務傳播行為類型
? ? ![]() ![]() |
?