天天看點

spring 聲明式事務例子

spring支援程式設計式事務管理和聲明式事務管理兩種方式。

程式設計式事務管理使用TransactionTemplate或者直接使用底層的PlatformTransactionManager。對于程式設計式事務管理,spring推薦使用TransactionTemplate。

聲明式事務管理建立在AOP之上的。其本質是對方法前後進行攔截,然後在目标方法開始之前建立或者加入一個事務,在執行完目标方法之後根據執行情況送出或者復原事務。聲明式事務最大的優點就是不需要通過程式設計的方式管理事務,這樣就不需要在業務邏輯代碼中摻雜事務管理的代碼,隻需在配置檔案中做相關的事務規則聲明(或通過基于@Transactional注解的方式),便可以将事務規則應用到業務邏輯中。

顯然聲明式事務管理要優于程式設計式事務管理,這正是spring倡導的非侵入式的開發方式。聲明式事務管理使業務代碼不受污染,一個普通的POJO對象,隻要加上注解就可以獲得完全的事務支援。和程式設計式事務相比,聲明式事務唯一不足地方是,後者的最細粒度隻能作用到方法級别,無法做到像程式設計式事務那樣可以作用到代碼塊級别。但是即便有這樣的需求,也存在很多變通的方法,比如,可以将需要進行事務管理的代碼塊獨立為方法等等。

聲明式事務管理也有兩種常用的方式,一種是基于tx和aop名字空間的配置檔案,另一種就是基于@Transactional注解。

以下是一個聲明式配置檔案事務例子,說明一下幾個關鍵設定點:
1,切入事務的位置,一般在service
2,逾時時間,我這裡設定了60秒,看具體項目業務設定
3,事務傳播行為,我這裡用了預設的TransactionDefinition.PROPAGATION_REQUIRED :如果目前存在事務,則加入該事務;如果目前沒有事務,則建立一個新的事務。這是預設值。
4,設定哪些關鍵方法需要開啟事務,一般insert,add,update,delete都要開戶事務。

package com.test.common.config;

import org.aspectj.lang.annotation.Aspect;
import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.interceptor.*;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

/**
 * @ClassName: TransactionConfig
 * @Description: 聲明式事務配置
 * @author: ljj
 * @date: 2019/03/29
 */
@Aspect
@Configuration
public class TransactionConfig {
    /**
     * 逾時時間
     */
    private static final int TX_METHOD_TIMEOUT = 60;

    /**
     * 切入點,統一切入到service層
     */
    private static final String AOP_POINTCUT_EXPRESSION = "execution (* com.test.service.*.*(..))";

    @Autowired
    private PlatformTransactionManager transactionManager;

    @Bean
    public TransactionInterceptor txAdvice() {
        NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource();

        /*隻讀事務,不做更新操作*/
        RuleBasedTransactionAttribute readOnlyTx = new RuleBasedTransactionAttribute();
        readOnlyTx.setReadOnly(true);
        readOnlyTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED);

        /*目前存在事務就使用目前事務,目前不存在事務就建立一個新的事務*/
        RuleBasedTransactionAttribute requiredTx = new RuleBasedTransactionAttribute();
        requiredTx.setRollbackRules(Collections.singletonList(new RollbackRuleAttribute(Exception.class)));
        requiredTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        requiredTx.setTimeout(TX_METHOD_TIMEOUT);

        Map<String, TransactionAttribute> txMap = new HashMap<>();
        //txMap.put("select*", requiredTx);
        txMap.put("add*", requiredTx);
        txMap.put("save*", requiredTx);
        txMap.put("insert*", requiredTx);
        txMap.put("update*", requiredTx);
        txMap.put("delete*", requiredTx);
        txMap.put("*", requiredTx);

        source.setNameMap(txMap);

        return new TransactionInterceptor(transactionManager, source);

    }

    @Bean
    public Advisor txAdviceAdvisor() {
        AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
        pointcut.setExpression(AOP_POINTCUT_EXPRESSION);
        return new DefaultPointcutAdvisor(pointcut, txAdvice());
    }
}
      

繼續閱讀