為什么要使用全局事務 在實際開發中,有些同學命名方法時不規范,多個成員開發時,會造成混亂,維護成本特別高,代碼可讀性不高.
怎么配置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()); } }