工具类-封装通用编程式事务
前言
大家都知道,spring为我们提供了编程式事务、声明式事务
一、编程式事务
声明式事务是大家使用得比较多的一种方式,这里就不再多说。
主要说下编程式事务,编程式事务的主要目的是减小事务粒度,使回滚数据可以是由开发人员手动控制,代码看起来更清晰些。同时在回滚时可以根据自己需求再处理点业务或记录些信息,当然开发起来也比声明式要多点步骤。
下面写一个简单的编程式事务实例。
1、有返回结果
public void manual() {
AccountCycleDo accountCycleDo = AccountCycleDo.create();
//第一次执行新增数据
dataSourceDao.insertTest(accountCycleDo);
//第二次执行新增数据,在下面因为唯一键冲突后回滚的只是第二次执行的新增数据
Integer num = transactionTemplate.execute(transactionStatus -> {
try {
//执行业务
return dataSourceDao.insertTest(accountCycleDo);
} catch (Exception e) {
log.error("有返回值,Exception,{}", e);
//回滚
transactionStatus.setRollbackOnly();
return -1;
}
});
}
2、无返回结果
public void manual() {
AccountCycleDo accountCycleDo = AccountCycleDo.create();
//第一次执行新增数据
dataSourceDao.insertTest(accountCycleDo);
//第二次执行新增数据,在下面因为唯一键冲突后回滚的只是第二次执行的新增数据
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
try {
//业务代码
dataSourceDao.insertTest(accountCycleDo);
} catch (Exception e) {
log.error("无返回值,Exception,{}", e);
//回滚
transactionStatus.setRollbackOnly();
}
}
});
}
都是比较简单的操作,但是如果需要使用的地方多了,每个地方都这样写还是比较麻烦的,所以做了一个简单的封装
二、封装通用工具类
1、编写工具类
package com.dili.util;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import javax.annotation.Resource;
import java.util.function.Function;
/**
* 手动处理事务
* @author jy
*/
@Component
@Slf4j
public class TransactionalUtil {
@Resource
private TransactionTemplate transactionTemplate;
/**
* 有返回值
* @param function
* @return
* @param <T>
*/
public <T> T transactionCallback(Function function){
Object o = transactionTemplate.execute(transactionStatus -> {
try {
//执行业务
return function.apply(new Object());
} catch (Exception e) {
log.error("有返回值,Exception,{}", e);
//回滚
transactionStatus.setRollbackOnly();
return null;
}
});
return (T) o;
}
/**
* 无返回值的
* @param function
*/
public void transactionCallbackWithoutResult(Function function){
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
try {
//业务代码
function.apply(new Object());
} catch (Exception e) {
log.error("无返回值,Exception,{}", e);
//回滚
transactionStatus.setRollbackOnly();
}
}
});
}
public void transactionCallbackWithoutResultOrRollback(Function function1, Runnable function2){
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
try {
//业务代码
function1.apply(new Object());
} catch (Exception e) {
log.error("无返回值,Exception,{}", e);
//回滚
transactionStatus.setRollbackOnly();
function2.run();
}
}
});
}
}
2、调用
public void manual() {
AccountCycleDo accountCycleDo = AccountCycleDo.create();
//第一次执行新增数据
dataSourceDao.insertTest(accountCycleDo);
//第二次执行新增数据,在下面因为唯一键冲突后回滚的只是第二次执行的新增数据
transactionUtil.transactionCallbackWithoutResult((a)-> dataSourceDao.insertTest(accountCycleDo));
Integer o = transactionUtil.transactionCallback((a) -> dataSourceDao.insertTest(accountCycleDo));
log.info("返回结果,{}",o);
//第三次执行,在回归时可以操作其他的
transactionUtil.transactionCallbackWithoutResultOrRollback((a)->{
dataSourceDao.insertTest(accountCycleDo);
return null;
},()-> log.info("回滚时,可以做其他的事情,{}",accountCycleDo));
}
这样抽取后就不用每次都写那么多了,几乎就是只专注业务代码就行了。
总结
简单记录下,丰富自己的工具库吧,大家加油!!!!!!