首先修改applicationContext.xml如下:
…<!-- 定義一個資料來源 --><bean id="dataSource" class="org.apache.tomcat.jdbc.pool.DataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/spring_test" /> <property name="username" value="root" /> <property name="password" value="root" /></bean><!-- 定義JdbcTemplate的Bean --><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate" p:dataSource-ref="dataSource"></bean><!-- 配置交易管理員 --><bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" p:dataSource-ref="dataSource"></bean><!-- enables scanning for @Transactional annotations --><tx:annotation-driven transaction-manager="txManager" /><!-- 在該Bean的代碼中標註@Transactional可以被交易管理員注入 --><bean id="userScore" class="net.hingyi.springDemo.transaction.service.UserScoreServiceImpl" p:userScoreRepository-ref="userScoreRepository_jdbc" /><bean id="userScoreRepository_jdbc" class="net.hingyi.springDemo.transaction.repository.UserScoreRepositoryImpl" p:jdbcTemplate-ref="jdbcTemplate" />…
實作類別代碼:
@Transactionalpublic class UserScoreRepositoryImpl implements UserScoreRepository {private JdbcTemplate jdbcTemplate;@Overridepublic UserScore getUserSocore(String userNo) {final UserScore us = new UserScore();...return us;}...}OK了。以上就實現了簡單的交易管理了。現在再稍微瞭解下@Transactional。
在設定檔中,預設情況下,<tx:annotation-driven>會自動使用名稱為transactionManager的交易管理員。
所以,如果定義的交易管理員名稱為transactionManager,那麼就可以直接使用<tx:annotation-driven/>。如下:
<!-- 配置交易管理員 --><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標註的位置
@Transactional註解可以標註在類和方法上,也可以標註在定義的介面和介面方法上。
如果我們在介面上標註@Transactional註解,會留下這樣的隱患:因為註解不能被繼承,所以業務介面中標註的@Transactional註解不會被業務實作類別繼承。所以可能會出現不啟動事務的情況。所以,Spring建議我們將@Transaction註解在實作類別上。
在方法上的@Transactional註解會覆蓋掉類上的@Transactional。
使用不同的交易管理員
如果我們要程式中使用多個交易管理員(主要是針對多資料來源的情況),可以通過以下的方式實現:
Service代碼:
public class MultiTxService {@Transactional("tran_1")public void addTest(int id){}@Transactional("tran_2")public void deleteTest(int id){}}applicationContext.xml配置如下:
<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>
經過以上的代碼,每個事務都會綁定各自的獨立的資料來源,進行各自的交易管理。我們可以最佳化下以上代碼,可以自訂一個綁定到特定交易管理員的註解,然後直接使用這個自訂的註解進行標識:
@Target({ElementType.METHOD,ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Transactional("tran_1")public @interface CustomerTransactional {}在Service代碼中使用:
...//使用名為tran_1的交易管理員@CustomerTransactionalpublic void addTest(String str){}…