為什么要使用全局事務 在實際開發中,有些同學命名方法時不規范,多個成員開發時,會造成混亂,維護成本特別高,代碼可讀性不高.
怎么配置Spring Boot全局事務 Spring Boot使用事務是非常簡單的,只需要在配置類或者啟動類上添加注解@EnableTransactionManagement開啟事務支持,然后在service層添加注解 @Transactional(rollbackFor = Exception.class)即可. 下面是全局事務代碼實現
特別提醒:mysql對應的表必須是InnoDB型才可支持事務,myisam不支持事務
package com.test.sketelon.util.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;
/**
* 全局事物配置
*
* @author David_hua
* @date 2019/8/15
* REQUIRED :如果當前存在事務,則加入該事務;如果當前沒有事務,則創建一個新的事務。
* SUPPORTS :如果當前存在事務,則加入該事務;如果當前沒有事務,則以非事務的方式繼續運行。
* MANDATORY :如果當前存在事務,則加入該事務;如果當前沒有事務,則拋出異常。
* REQUIRES_NEW :創建一個新的事務,如果當前存在事務,則把當前事務掛起。
* NOT_SUPPORTED :以非事務方式運行,如果當前存在事務,則把當前事務掛起。
* NEVER :以非事務方式運行,如果當前存在事務,則拋出異常。
* NESTED :如果當前存在事務,則創建一個事務作為當前事務的嵌套事務來運行;如果當前沒有事務,則該取值等價於 REQUIRED 。
* 指定方法:通過使用 propagation 屬性設置,例如:@Transactional(propagation = Propagation.REQUIRED)
* 參考文章;https://blog.csdn.net/schcilin/article/details/93306826
*/
@Aspect
@Configuration
public class TransactionAdviceConfig {
/**
* 配置方法過期時間,默認-1,永不超時
*/
private final static int TX_METHOD_TIME_OUT = 10;
/**
* 全局事務位置配置 在哪些地方需要進行事務處理:具體如下
* 配置切入點表達式,這里解釋一下表達式的含義
* 1.execution(): 表達式主體
* 2.第一個*號:表示返回類型,*號表示所有的類型
* 3.com.schcilin.goods.service表示切入點的包名
* 4.第二個*號:表示實現包
* 5.*(..)*號表示所有方法名,..表示所有類型的參數
*/
private static final String POITCUT_EXPRESSION = "execution(* com.test.sketelon.service.*.*(..))";
@Autowired
private PlatformTransactionManager platformTransactionManager;
@Bean
public TransactionInterceptor txadvice() {
/** 配置事務管理規則
nameMap聲明具備需要管理事務的方法名.
這里使用public void addTransactionalMethod(String methodName, TransactionAttribute attr)
*/
NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource();
Map<String, TransactionAttribute> nameMap = new HashMap<>(16);
/*只讀事物、不做更新刪除等*/
/*事務管理規則*/
RuleBasedTransactionAttribute readOnlyRule = new RuleBasedTransactionAttribute();
/*設置當前事務是否為只讀事務,true為只讀*/
readOnlyRule.setReadOnly(true);
/* transactiondefinition 定義事務的隔離級別;
* PROPAGATION_REQUIRED 如果當前沒有事務,就新建一個事務,如果已經存在一個事務中,加入到這個事務中*/
readOnlyRule.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
RuleBasedTransactionAttribute requireRule = new RuleBasedTransactionAttribute();
/*拋出異常后執行切點回滾*/
requireRule.setRollbackRules(Collections.singletonList(new RollbackRuleAttribute(Exception.class)));
/*PROPAGATION_REQUIRED:事務隔離性為1,若當前存在事務,則加入該事務;如果當前沒有事務,則創建一個新的事務。這是默認值。 */
requireRule.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
/*設置事務失效時間,超過10秒,可根據hytrix,則回滾事務*/
requireRule.setTimeout(TX_METHOD_TIME_OUT);
nameMap.put("add*", requireRule);
nameMap.put("save*", requireRule);
nameMap.put("insert*", requireRule);
nameMap.put("update*", requireRule);
nameMap.put("delete*", requireRule);
nameMap.put("remove*", requireRule);
/*進行批量操作時*/
nameMap.put("batch*", requireRule);
nameMap.put("get*", readOnlyRule);
nameMap.put("query*", readOnlyRule);
nameMap.put("find*", readOnlyRule);
nameMap.put("select*", readOnlyRule);
nameMap.put("count*", readOnlyRule);
source.setNameMap(nameMap);
return new TransactionInterceptor(platformTransactionManager, source);
}
/**
* 設置切面=切點pointcut+通知TxAdvice
*
* @return
*/
@Bean
public Advisor txAdviceAdvisor() {
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
pointcut.setExpression(POITCUT_EXPRESSION);
return new DefaultPointcutAdvisor(pointcut, txadvice());
}
}
