1、SpringBoot中可以使用PlatformTransactionManager接口來實現事務的統一控制,而進行控制的時候也可以采用注解或者AOP切面配置形式來完成,建議進行Aop切面進行事務管理,但是要寫好注釋,不然一些人后期找代碼邏輯很容易看懵逼的。
在業務層的方法上啟用事務控制,可以加到方法上,也可以加到該業務類上,根據自己的需求來進行。
1 package com.demo.service.impl; 2 3 import java.util.List; 4 5 import org.springframework.beans.factory.annotation.Autowired; 6 import org.springframework.stereotype.Service; 7 import org.springframework.transaction.annotation.Propagation; 8 import org.springframework.transaction.annotation.Transactional; 9 10 import com.demo.dao.UserDao; 11 import com.demo.po.UserInfo; 12 import com.demo.service.UserService; 13 14 @Service 15 public class UserServiceImpl implements UserService { 16 17 @Autowired 18 private UserDao userDao; 19 20 /** 21 * 在業務層的方法上啟用事務管理 22 */ 23 @Transactional(propagation = Propagation.REQUIRED, readOnly = true) 24 @Override 25 public List<UserInfo> findAll() { 26 27 return userDao.findAll(); 28 } 29 30 }
在程序主類中還需要配置事務管理注解,使用注解@EnableTransactionManagement開啟事務。
1 package com.demo; 2 3 import org.springframework.boot.SpringApplication; 4 import org.springframework.boot.autoconfigure.SpringBootApplication; 5 import org.springframework.data.jpa.repository.config.EnableJpaRepositories; 6 import org.springframework.transaction.annotation.EnableTransactionManagement; 7 8 @SpringBootApplication // 啟動Springboot程序,而后自帶子包掃描 9 @EnableJpaRepositories(basePackages = "com.demo.dao") 10 @EnableTransactionManagement // 啟動事務管理 11 public class DemoApplication { 12 13 public static void main(String[] args) { 14 // 啟動Springboot程序 15 SpringApplication.run(DemoApplication.class, args); 16 } 17 18 }
如果在業務層中定義@Transactional注解實現事務的控制,全部使用注解控制必然會造成代碼的大量重復。在實際工作中,SpringBoot與事務結合最好的控制方法就是定義一個事務的配置類。取消業務Service層的事務注解配置,並定義TransactionConfig配置類,如下所示:
1 package com.demo.config; 2 3 import java.util.HashMap; 4 import java.util.Map; 5 6 import org.aspectj.lang.annotation.Aspect; 7 import org.springframework.aop.Advisor; 8 import org.springframework.aop.aspectj.AspectJExpressionPointcut; 9 import org.springframework.aop.support.DefaultPointcutAdvisor; 10 import org.springframework.beans.factory.annotation.Autowired; 11 import org.springframework.context.annotation.Bean; 12 import org.springframework.context.annotation.Configuration; 13 import org.springframework.transaction.PlatformTransactionManager; 14 import org.springframework.transaction.TransactionDefinition; 15 import org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource; 16 import org.springframework.transaction.interceptor.RuleBasedTransactionAttribute; 17 import org.springframework.transaction.interceptor.TransactionAttribute; 18 import org.springframework.transaction.interceptor.TransactionInterceptor; 19 20 @Configuration // 定義配置Bean 21 @Aspect // 采用Aop切面處理,定義切面類,切面通常是指封裝的用於橫向插入系統功能(事務、日志)的類。 22 public class TransactionConfig { 23 24 private static final int TRANSACTION_METHOD_TIMEOUT = 5; // 事務超時時間為5秒鍾 25 26 // 定義切面表達式 27 private static final String AOP_POINTCUT_EXPRESSION = "execution(* com.demo..service.*.*(..))"; 28 29 // 注入事務管理對象 30 @Autowired 31 private PlatformTransactionManager transactionManager; 32 33 /** 34 * 切面名稱必須為txAdvice 35 * 36 * @return 37 */ 38 @Bean(value = "txAdvice") 39 public TransactionInterceptor transactionConfig() { 40 // 定義只讀事務控制,該事務不需要啟動事務支持 41 RuleBasedTransactionAttribute readOnly = new RuleBasedTransactionAttribute(); 42 // 設置只讀事務 43 readOnly.setReadOnly(true); 44 readOnly.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED); 45 46 // 定義更新事務,同時設置事務操作的超時時間 47 RuleBasedTransactionAttribute required = new RuleBasedTransactionAttribute(); 48 required.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); 49 // 設置事務超時時間為5秒鍾 50 required.setTimeout(TRANSACTION_METHOD_TIMEOUT); 51 52 // 定義業務切面 53 Map<String, TransactionAttribute> transactionmap = new HashMap<String, TransactionAttribute>(); 54 transactionmap.put("add*", required); 55 transactionmap.put("edit*", required); 56 transactionmap.put("delete*", required); 57 transactionmap.put("get*", readOnly); 58 transactionmap.put("list*", readOnly); 59 transactionmap.put("find*", readOnly); 60 61 // 使用名稱匹配 62 NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource(); 63 source.setNameMap(transactionmap); 64 65 // 對設置名稱的方法進行事務操作 66 TransactionInterceptor transactionInterceptor = new TransactionInterceptor(); 67 transactionInterceptor.setTransactionManager(transactionManager); 68 transactionInterceptor.setTransactionAttributeSource(source); 69 70 // 返回事務信息 71 return transactionInterceptor; 72 } 73 74 @Bean 75 public Advisor transactionAdviceAdvisor() { 76 AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut(); 77 // 定義切面 78 pointcut.setExpression(AOP_POINTCUT_EXPRESSION); 79 DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(pointcut, transactionConfig()); 80 return advisor; 81 } 82 83 }
此時程序中的事務控制可以利用TransactionConfig類結合AspectJ切面與業務層中的方法匹配,而后就不再需要業務方法使用@Transactional注解重復定義了,需要注意的是啟動主類要加上@EnableTransactionManagement啟動事務管理。