Spring事务实战之@Transactional

前言:在开发中,需要在一个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

ServiceExceptionServiceException1都是继承自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)的使用

你可能感兴趣的:(Spring事务实战之@Transactional)