前言:在开发中,需要在一个service中调用serviceA插入数据库和servcieB插入数据库,存在serivceA插入成功,而serivceB报异常插入数据失败,导致脏数据;解决办法就是在service上加上@Transactional关键字,就可以serivceB插入失败时将serviceA插入成功的数据回滚。
@Transactional(rollbackFor=Exception.class)
@Transactional(rollbackFor=Exception.class)
在项目中,@Transactional(rollbackFor=Exception.class),如果类加了这个注解,那么这个类里面的方法抛出异常,就会回滚,数据库里面的数据也会回滚。
在@Transactional注解中如果不配置rollbackFor属性,那么事务只会在遇到RuntimeException的时候才会回滚,加上rollbackFor=Exception.class,可以让事务在遇到非运行时异常时也回滚
例子1:
抛非检查异常SQLException,@Transactional不会发生回滚
fun1方法操作成功,fun2方法操作失败,这种当fun2方法失败时,fun1方法对数据的操作不会发生回滚
public void fun2(Data data) throws SQLException {
try {
// 插入记录到数据库
return dataMapper.addData(data);
} catch (Exception e) {
// 异常捕获后抛出受检查型异常SQLException
throw new SQLException();
}
}
@Transactional
public ReturnModel fun(Data data) throws SQLException {
fun1(data);
fun2(data);
}
例子2
抛非检查异常SQLException,@Transactional(rollbackFor = Exception.class)会回滚
fun1方法操作成功,fun2方法操作失败,这种当fun2方法失败时,fun1方法对数据的操作会发生回滚
public void fun2(Data data) throws SQLException {
try {
// 插入记录到数据库
dataMapper.addData(data);
} catch (Exception e) {
// 异常捕获后抛出受检查型异常SQLException
throw new SQLException();
}
}
// rollbackFor指定异常Exception
@Transactional(rollbackFor = Exception.class)
public ReturnModel fun(Data data) throws SQLException {
fun1(data);
fun2(data);
}
例子3
异常捕获处理后不抛出,也不会发生回滚
fun1方法操作成功,fun2方法操作失败,这种当fun2方法失败时将异常捕获解决,fun1方法对数据的操作不会发生回滚
public void fun2(Data data) {
try {
// 插入记录到数据库
dataMapper.addData(data);
} catch (Exception e) {
// 异常捕获后catch打log
logger.debug("exception: {}", e.getClass().getName());
}
}
@Transactional
public ReturnModel fun(Data data) {
fun1(data);
fun2(data);
}
例子4
ServiceException、ServiceException1都是继承自RuntimeException的异常类,
fun1方法操作成功,fun2方法操作失败,这种当fun2方法失败时,fun1方法对数据的操作会发生回滚,并不能通过rollbackFor指定对哪个运行时异常进行事务回滚,换句话说rollbackFor的粒度不能区分不同的运行时异常
public void fun2(Data data) {
try {
// 插入记录到数据库
dataMapper.addData(data);
} catch (Exception e) {
// 异常捕获后抛出受检查型异常ServiceException
throw new ServiceException();
}
}
// rollbackFor指定异常ServiceException1
@Transactional(rollbackFor = ServiceException1.class)
public ReturnModel fun(Data data) {
fun1(data);
fun2(data);
}
Spring框架的事务处理代码默认地只在抛出运行时和unchecked exceptions时才标识事务回滚。 也就是说,当抛出个RuntimeException 或其子类的实例时,(Errors 也一样 - 默认地 - 标识事务回滚。)从事务方法中抛出的Checked exceptions将不被标识进行事务回滚。
1、让checked例外也回滚:在整个方法前加上 @Transactional(rollbackFor=Exception.class)
2、让unchecked例外不回滚: @Transactional(notRollbackFor=RunTimeException.class)
3、不需要事务管理的(只查询的)方法:@Transactional(propagation=Propagation.NOT_SUPPORTED)
注意: 如果异常被try{...}catch{...}了,事务就不回滚了,如果想让事务回滚必须再往外抛try{...}catch{throw Exception}。
参考
【1】Spring中的@Transactional(rollbackFor = Exception.class)属性详解
【2】@Transactional(rollbackFor=Exception.class)的使用








网友评论