起头自述
SpringBoot的事务管理和Spring的事务管理一样,只是SpringBoot相对而言更简单,不用配置事务管理器,省去配置文件的各种配置,只需要在application.yml中配置一个数据源即可。
编程式事务管理
- 使用
TransactionTemplate
使用TransactionTemplate
管理事务时仅需设置好数据源之后,在项目中注入即可,下面的代码演示使用TransactionTemplate
,封装了两个方法,一个执行又返回结果的事务,一个执行无返回结果的事务。
/**
* 编程式事物管理方式
*
* @author Juniter
* @date 2017-11-17
*/
@Service
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class TransactionService {
private static final Logger logger = LoggerFactory.getLogger(TransactionService.class);
private final TransactionTemplate transactionTemplate;
//通过构造方法注入一个PlatformTransactionManager SpringBoot会自动完成
public TransactionService(PlatformTransactionManager transactionManager) {
Assert.notNull(transactionManager, "The 'transactionManager' argument must not be null.");
this.transactionTemplate = new TransactionTemplate(transactionManager);
//设置超时时间
this.transactionTemplate.setTimeout(300000);
//设置事物策略
this.transactionTemplate.setIsolationLevel(TransactionDefinition.ISOLATION_REPEATABLE_READ);
}
/**
* 执行有返回结果的事物
* @param executer
* @param o 具体逻辑所需要的参数
* @return 执行后的返回结果
*/
public <T> T doTransaction(final Executer<T> executer,Object...o) {
return this.transactionTemplate.execute(new TransactionCallback<T>() {
@Override
public T doInTransaction(TransactionStatus status) {
T t = null;
try {
t = executer.execute(o);
}catch(Exception e) {
//一旦出现异常便回滚
status.setRollbackOnly();
logger.error("Rollback For - > {}",e.getMessage());
}
return t;
}
});
}
/**
* 执行没有返回结果的事物
* @param executer
* @param o 具体逻辑所需要的参数
*/
public void doTransactionWithoutResult(final ExecuterWithoutResult executer,Object...o) {
this.transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
try {
executer.execute(o);
}catch (Exception e) {
//一旦出现异常便回滚
status.setRollbackOnly();
logger.error("Rollback For - > {}",e.getMessage());
}
}
});
}
}
/**
* 该接口用于执行具体的事物
* @author Juniter
*
* @param <T>
*/
@FunctionalInterface
public interface Executer<T> {
T execute(Object... o) throws Exception;
}
/**
* 该接口用于执行具体的事物
* @author Juniter
*
* @param <T>
*/
@FunctionalInterface
public interface ExecuterWithoutResult {
void execute(Object... o) throws Exception;
}
以下是一个使用的例子
@Service
public class TransactionSampleServcie {
//注入事务管理的Service
@Autowired
private TransactionService transactionService;
@Autowired
private CityMapper cityMapper;
@Autowired
private HotelMapper hotelMapper;
public void addNewHotel(HotelInfomation info) {
this.transactionService.doTransactionWithoutResult(this::insertWithTransaction,info);
}
/**
* 在该方法中执行的操作都是事务性的。
* @param info
* @throws Exception
*/
private void insertWithTransaction(Object...info) throws Exception {
HotelInfomation hotelInfo = (HotelInfomation) info[0];
Hotel hotel = new Hotel();
hotel.setAddress(hotelInfo.getAddress());
hotel.setName(hotelInfo.getName());
hotel.setZip(hotelInfo.getZip());
//按照名称查询City
City city = this.cityMapper.selectCityByName(hotelInfo.getCity());
if(city !=null) {
hotel.setCity(city.getId());
}else {
city = new City();
city.setName(hotelInfo.getCity());
city.setCountry(hotelInfo.getCountry());
city.setState(hotelInfo.getState());
//保存City
this.cityMapper.insertCity(city);
//获取刚插入的City
city = this.cityMapper.selectCityByName(hotelInfo.getCity());
hotel.setCity(city.getId());
}
//看看Hotel是否存在,不存在便插入。
if(this.hotelMapper.selectHotelByExample(hotel)==null)
this.hotelMapper.insertHotel(hotel);
//throw new NullPointerException("测试事务回滚");
}
}
声明式事务管理
声明式事务管理 在SpringBoot中直接使用@Transactional
注解便可,如下代码
@Service
public class AnnotatedTransaction {
@Autowired
private CityMapper cityMapper;
@Autowired
private HotelMapper hotelMapper;
//该方法是事务性的,若要更多设置,请参照@Transactional注解,源码内有详细说明
@Transactional(rollbackFor = Exception.class)
public void insertWithTransaction(HotelInfomation info) throws Exception {
Hotel hotel = new Hotel();
hotel.setAddress(info.getAddress());
hotel.setName(info.getName());
hotel.setZip(info.getZip());
// 按照名称查询City
City city = this.cityMapper.selectCityByName(info.getCity());
if (city != null) {
hotel.setCity(city.getId());
} else {
city = new City();
city.setName(info.getCity());
city.setCountry(info.getCountry());
city.setState(info.getState());
//保存City
this.cityMapper.insertCity(city);
//获取刚插入的City
city = this.cityMapper.selectCityByName(info.getCity());
hotel.setCity(city.getId());
}
//看看Hotel是否存在,不存在便插入。
if (this.hotelMapper.selectHotelByExample(hotel) == null)
this.hotelMapper.insertHotel(hotel);
//throw new Exception("测试事务回滚");
}
}