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());
}
}