Spring 事務管理

1. 事務的概念與特性

事務指的是邏輯上的一組操作,這組操作要麼全部成功,要麼全部失敗;用統一的機制來處理不同數據訪問技術的事務處理;

特性 描述
原子性-atomicity 事務中的各個操作不可單獨執行,要麼整體發生,要麼整體不發生
一致性-consistency 事務執行前後的數據完整性必需保持一致
隔離性-isolation 事務執行過程中不應該被其他事務干擾,多個併發事務之間的數據要互相隔離
持久性-durability 一個事務一旦提交,數據庫中數據的改變就是永久性的

2. 事務管理 API

由 Spring 提供常用的 3 個 API 實現事務的管理

2.1 PlatformTransactionManager-事務管理器

常用事務 描述
org.springframework.jdbc.datasource.DataSourceTransactionManager Spring JDBC 或 Batis 進行持久化數據使用
org.springframework.orm.hibernate3.HibernateTransactionManager Hiberbate 3.0 版本進行持久化數據使用

2.2 TransactionDefinition-事務定義信息

隔離級別 描述
READ_UNCOMMITED 最低隔離級別,充許別外一個事務可以看到這個事務未提交的數據。這種隔離級別會產生髒讀,不可重複讀和幻像讀
READ_COMMITTED 保證一個事務修改的數據提交後才能被另外一個事務讀取。另外一個事務不能讀取該事務未提交的數據。這種事務隔離級別可以避免髒讀出現,但是可能會出現不可重複讀和幻像讀
REPEAtABLE_READ 防止髒讀,不可重複讀。但是可能出現幻像讀。它除了保證一個事務不能讀取另一個事務未提交的數據外,還保證了避免下面的情況產生(不可重複讀)
SERIALIZABLE 花費最高代價但是最可靠的事務隔離級別,事務被處理爲順序執行。除了防止髒讀,不可重複讀外,還避免了幻像讀
傳播行爲 描述
REQUIRED 支持當前事務,如果不存在則創建
SUPPORTS 支持當前事務,如果不存在就不使用
MANDATORY 支持當前事務,如果不存在便拋出異常
REQUIRES_NEW 如果有事務存在,掛起事務並創建新事物
NOT_SUPPORTED 以非事務方式運行,如果事務存在則掛起當前事務
NEVER 以非事務方式運行,如果事務存在則拋出異常
NESTED 如果當前事務存在,則嵌套事務執行

2.3 TransactionStatus-事務狀態表現形式


3. 事務管理方式

3.1 編程式事務管理

  • 業務類實現.class
public class ServiceImpl{

    // 注入事務管理的模板
    private TransactionTemplate transactionTemplate;

    public void setTransactionTemplate(TransactionTemplate t){
        this.transactionTemplate = t;
    }

    // 某個測試業務方法
    public void tansactionTest(){
        transactionTemplate.execute(new TransactionCallbackWithoutResult()){
            @Override
            protected void doInTransactionWithResult(TransactionStatus transactionStatus){
                // 此處可以開始執行事務中的相關操作
            }
        }
    }
}
  • 編輯配置文件.xml
<beans ...>

    <!-- 配置c3p0連接池 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driverClass}"/>
        <property name="jdbcUrl" value="${jdbc.url}"/>
        <property name="user" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>

    <!-- 配置事務管理器,關聯連接池 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!-- 配置事務管模板,事務包裝 -->
    <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
        <property name="transactionManager" ref="transactionManager"/>
    </bean>

    <!-- 業務類,模板應用 -->
    <bean id="service" class="com...ServiceImpl">
        <!-- 注入事務管理的模板 -->
        <property name="transactionTemplate" ref="transactionTemplate"/>
    </bean>

</beans>

3.2 聲明式事務管理 - 推薦

3.2.1 基於 TransactionProxyFactoryBean 方式

需爲每個事務管理的類都配置一個 TransactionProxyFactoryBean 。需要引入兩包:

  • com.springsource.org.aopalliance.jar
  • spring-aop.jar
  • 業務類實現.class
public class ServiceImpl{

    // 某個測試業務方法
    public void tansactionTest(){
        // 此處可以開始執行事務中的相關操作
    }
}
  • 編輯配置文件.xml
<beans ...>

    <!-- 配置c3p0連接池 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driverClass}"/>
        <property name="jdbcUrl" value="${jdbc.url}"/>
        <property name="user" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>

    <!-- 業務類 -->
    <bean id="service" class="com...ServiceImpl"></bean>

    <!-- 配置事務管理器,關聯連接池 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!-- 業務層代理-->
    <bean id="accountServiceProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
        <!-- 關聯目標對象 -->
        <property name="target" ref="service"/>
        <!-- 注入事務管理器 -->
        <property name="transactionManager" ref="transactionManager"/>
        <!-- 注入事務屬性,代替目標對象完成注入工作 -->
        <property name="transactionAtteributes">
            <props>
                <!--
                    prop 格式:
                        PROPAGATION : 事務的傳播行爲;
                        ISOLATION   : 事務的隔離級別;
                        readOnly    : 只讀;
                        -Exception  : 指定發生異常執行回滾;
                        +Exception  : 指定發生異常依然提交事務,不自信回滾;
                -->
                <prop key"transfer">PROPAGATION_REQUIRED</prop>
            </props>
        </property>
    </bean>
</beans>

3.2.2 基於 AspectJ 方式

只需在 xml 配置中實現事務的增強式管理,而對應的類無需任何操作。需要引入兩包:

  • com.springsource.org.aspectj.weaver.jar
  • spring-aspects.jar
  • 業務類實現.class
public class ServiceImpl{

    // 某個測試業務方法
    public void tansactionTest(){
        // 此處可以開始執行事務中的相關操作
    }
}
  • 編輯配置文件.xml
<beans ...>

    <!-- 配置c3p0連接池 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driverClass}"/>
        <property name="jdbcUrl" value="${jdbc.url}"/>
        <property name="user" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>

    <!-- 業務類 -->
    <bean id="service" class="com...ServiceImpl"></bean>

    <!-- 配置事務管理器,關聯連接池 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!-- 配置事務的通知:(事務增強) -->
    <tx:advice id="txAdvice" transaction-manager"="transactionManager">
        <tx:attributes>
            <!--
                propagation    : 事務的傳播行爲;
                isolation      : 事務的隔離級別;
                read-only      : 只讀;
                rollback-for   : 指定發生異常執行回滾;
                no-rollback-for: 指定發生異常依然提交事務,不自信回滾;
                timeout        : 過期信息;
            -->
            <tx:method name="transfer" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>

    <!-- 配置切面 -->
    <aop:config>
        <!-- 設定切入點 -->
        <aop:pointcut expression="execution(* com...ServiceImpl+.*(..))" id="pointcut"/>
        <!-- 設定切面 -->
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut"/>
    </aop:config>
</beans>

3.2.2 基於註解方式

除 xml 配置並開啓事務以外,還需要爲每個事務管理類添加相應的註解信息。

  • 業務類實現.class
/*
propagation    : 事務的傳播行爲;
isolation      : 事務的隔離級別;
readOnly       : 只讀;
rollbackFor    : 指定發生異常執行回滾;
noRollbackFor  : 指定發生異常依然提交事務,不自信回滾;

注意:方法亦可以加該註解,標識覆蓋類聲明的註解信息。
*/
@Transactional(propagation=Propagation.REQUIRED)
public class ServiceImpl{

    // 某個測試業務方法
    public void tansactionTest(){
        // 此處可以開始執行事務中的相關操作
    }
}
  • 編輯配置文件.xml
<beans ...>

    <!-- 配置c3p0連接池 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driverClass}"/>
        <property name="jdbcUrl" value="${jdbc.url}"/>
        <property name="user" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>

    <!-- 業務類 -->
    <bean id="service" class="com...ServiceImpl"></bean>

    <!-- 配置事務管理器,關聯連接池 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!-- 開啓註解事務,配置文件.class 可用 @EnableTransactionManagement 啓用事務 -->
    <tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章