spring 编程式事务实现
在spring中实现事务管理的方式主要有两种,声明式和编程式。声明式:使用@Transactional注解。本文主要讲解关于编程式事务的实现方式
一、使用TransactionTemplate 实现编程式事务
该类的使用方式主要是通过 模板方法的形式,其核心执行业务是调用TransactionTemplate的execute()方法。
execute方法:
<T> T execute(TransactionCallback<T> action) throws TransactionException;
需要参数为一个回调接口TransactionCallback。该接口是函数式接口,因此也可以采用函数式编程的方式来完成具体模板方法的实现
简单使用方法如下:
public int insertUser(SysUserEntity userEntity){
int i = transactionTemplate.execute(status -> {
int j = 0;
int result = userDao.insertSysUser(userEntity);
// j = 10 /j;
return result;
});
return i;
}
注意:
- 通常项目中我们注入的事务管理器为PlatformTransactionManager。因此直接使用template可能会出现无法装配的情况。需要手动定义创建transactionTemplate的bean
@Bean
public TransactionTemplate transactionTemplate(PlatformTransactionManager platformTransactionManager){
TransactionTemplate transactionTemplate = new TransactionTemplate();
transactionTemplate.setTransactionManager(platformTransactionManager);
return transactionTemplate;
}
二、使用PlatformTransactionManager 实现编程式事务
- 在service中装配platformTransactionManager
@Autowired
private PlatformTransactionManager txManager ;
- 业务代码中使用该事务管理器
// 可以通过在def中设置相关的传递属性,独立性等信息
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
TransactionStatus status = txManager.getTransaction(def);
int result = 0;
try{
result = sysUserDao.insertSysUser(userEntity);
Thread.sleep(1_000);
txManager.commit(status);
}catch (Exception e){
txManager.rollback(status);
}
return result;
注意:
- 在项目中使用new DefaultTransactionDefinition();一定要注意不要随意的创建垃圾对象
有可能会造成垃圾对象,一直存活。批处理程序时导致事务挂起。而造成程序卡死的现象
比如下述错误示例:
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
TransactionStatus status = txManager.getTransaction(def);
def = new DefaultTransactionDefinition();
status = txManager.getTransaction(def);
三、利用AOP简单实现事务注解
1、引入spring 切面依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring-version}</version>
</dependency>
2、自定义注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SelfTransaction {
// 定义相关属性来实现 复制事务的传播特性,隔离级别等
}
3、定义切面类
可以通过自定义注解不同的属性,在切面类中获取注解对应不同的值来设置相应事务隔离级别等相关信息。
@Aspect
@EnableAspectJAutoProxy
@Component
public class SelfTransactionAspect {
@Autowired
private PlatformTransactionManager txManager;
@Pointcut("@annotation(com.sz.base.annotation.SelfTransaction)")
public void logPointCut() {}
@Around("logPointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
MethodSignature signature = (MethodSignature) point.getSignature();
Method method = signature.getMethod();
//获得注解
SelfTransaction transaction = method.getAnnotation(SelfTransaction.class);
// 通过定义注解的属性,在此处获取相关属性来设置事务的隔离级别等信息
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
TransactionStatus status = txManager.getTransaction(def);
Object result = null;
try{
result = point.proceed();
txManager.commit(status);
}catch (Exception e){
txManager.rollback(status);
throw new RuntimeException(e.getMessage());
}
return result;
}
}
4、在service中使用
@SelfTransaction
public int insertUser(SysUserEntity userEntity){
int j = 0;
int result = sysUserDao.insertSysUser(userEntity);
//result = result/j;
return result;
}