Spring事務管理總結

jopen 9年前發布 | 19K 次閱讀 Spring JEE框架

在項目開發過程中經常會使用事務來確保數據的一致性。根據網上的資料整理一下在spring中配置事務的幾種方式。無論是哪種方式都需要在配置文件中配置連接池和事務管理器,代碼如下。

   <!-- 讀取配置文件 -->
<bean
     class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
     <property name="locations">
         <list>
             <value>classpath:database.properties</value>
             <value>classpath:service.properties</value>
         </list>
     </property>
     <property name="fileEncoding" value="UTF-8" />
     <property name="ignoreResourceNotFound" value="false" />
 </bean>
 <!--連接池 -->
 <bean id="dataSource"
     class="org.springframework.jdbc.datasource.DriverManagerDataSource">
     <property name="driverClassName" value="${db.driver}" />
     <property name="url" value="${db.url}" />
     <property name="username" value="${db.username}" />
     <property name="password" value="${db.password}" />
 </bean>
 <!-- 配置事務管理器 -->
 <bean id="transactionManager"
     class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
     <property name="dataSource" ref="dataSource" />
 </bean>

聲明式事務管理

基于AspectJ的XML方式的配置

這是我覺得最好的方式,基于aop配置,當新增的方法要使用事務管理時,無需修改代碼。首先在配置文件xml中引入aop和tx的命名空間

xmlns:tx="http://www.springframework.org/schema/tx" 
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop   
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"

然后在xml中加入aop的配置,下面的配置就是在services的切入點上應用txAdvice的增強,services的切入點就是ymy.com.service.impl包下的所有方法應用txAdvice的增強。然后txAdvice是在所有以create,add,delete,update,change開頭的方法上加上事務管理。

 <!-- 定義事務通知 (事務的增強)-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <!-- 定義方法的過濾規則 -->
    <tx:attributes>
        <!-- 所有方法都使用事務 -->
        <!-- 
            propagation:事務傳播行為
            isolation:事務隔離
            read-only:只讀
            rollback-for:發生哪些異常回滾
            no-rollback-for:發生哪些異常不回滾 
            timeout:過期信息    
         -->
        <tx:method name="create*" propagation="REQUIRED"/>
        <tx:method name="add*" propagation="REQUIRED"/>
        <tx:method name="delete*" propagation="REQUIRED"/>
        <tx:method name="update*" propagation="REQUIRED"/>
        <tx:method name="change*" propagation="REQUIRED"/>
    </tx:attributes>
</tx:advice>
<!-- 定義AOP配置 配置切面 -->
<aop:config>
    <!-- 定義一個切入點 -->
    <aop:pointcut expression="execution (* ymy.com.service.impl.*.*(..))" id="services"/>
    <!-- 對切入點和事務的通知,進行適配 -->
    <aop:advisor advice-ref="txAdvice" pointcut-ref="services"/>
</aop:config>

采用這種方式配置,當方法是按照事務定義的規則命名時,都會加入事務管理。

基于注解

這種方式是我覺得最簡單的,第二推薦。要采用注解的方式,需要在配置文件中開啟注解事務。

<!-- 開啟注解事務 -->
<tx:annotation-driven transaction-manager="transactionManager"/>

在使用時只需在對應的類上添加注解@Transactional即可

@Service
@Transactional
public class TaskService implements ITaskService {

}</pre>

也可在使用注解時定義事物的傳播級別 隔離行為等。。

<pre>@Transactional(propagation=Propagation.REQUIRED)</pre>

基于TransactionProxyFactoryBean

這種方式配置比較麻煩,需要為每一個需要事務管理的類配置一個代理類,不推薦使用。例如我要對taskService進行事務管理,需要如下配置,用代理類對目標類進行增強。

 <!-- 配置service層的代理 -->
<bean id = "taskServiceProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
    <!-- 配置目標對象 -->
    <property name = "target" ref="taskService"></property>
    <!-- 注入事務管理器 -->
    <property name = "transactionManager" ref="transactionManager"></property>
    <!-- 設置需要事務管理的方法 -->
    <property name="transactionAttributes">
        <props>
            <prop key="update*">PROPAGATION_REQUIRED</prop>
        </props>
    </property>
</bean>

之后在注入service類時,就要注入它的代理類。

@Resource(name = "taskServiceProxy")
private ITaskService taskSerivce;

編程式事務管理

超級不推薦,需要為每個類注入事務模板,然后在需要事務管理的方法中使用事務模板。

private TransactionTemplate transactionTemplate;
public void test(){
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                //進行事務相應的操作。。。
                //方法一...
                //方法二...
            }
        });
    }
原文 http://segmentfault.com/a/1190000003739293

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!