自用

坑点1:遇到非检测异常时,事务开启,也无法回滚。 例如下面这段代码,用户依旧增加成功,并没有因为后面遇到检测异常而回滚!!

@Transactional
public int insertUser(User user) throws Exception
{
    // 新增用户信息
    int rows = userMapper.insertUser(user);
    // 新增用户岗位关联
    insertUserPost(user);
    // 新增用户与角色管理
    insertUserRole(user);
    // 模拟抛出SQLException异常
    boolean flag = true;
    if (flag)
    {
        throw new SQLException("发生异常了..");
    }
    return rows;
}

  分析:因为Spring的默认的事务规则是遇到运行异常(RuntimeException)和程序错误(Error)才会回滚。如果想针对非检测异常进行事务回滚,可以在@Transactional 注解里使用 rollbackFor 属性明确指定异常。
例如下面这样,就可以正常回滚:

@Transactional(rollbackFor = Exception.class)
public int insertUser(User user) throws Exception
{
    // 新增用户信息
    int rows = userMapper.insertUser(user);
    // 新增用户岗位关联
    insertUserPost(user);
    // 新增用户与角色管理
    insertUserRole(user);
    // 模拟抛出SQLException异常
    boolean flag = true;
    if (flag)
    {
        throw new SQLException("发生异常了..");
    }
    return rows;
}

  

坑点2: 在业务层捕捉异常后,发现事务不生效。 这是许多新手都会犯的一个错误,在业务层手工捕捉并处理了异常,你都把异常“吃”掉了,Spring自然不知道这里有错,更不会主动去回滚数据。
例如:下面这段代码直接导致用户新增的事务回滚没有生效。

@Transactional
public int insertUser(User user) throws Exception
{
    // 新增用户信息
    int rows = userMapper.insertUser(user);
    // 新增用户岗位关联
    insertUserPost(user);
    // 新增用户与角色管理
    insertUserRole(user);
    // 模拟抛出SQLException异常
    boolean flag = true;
    if (flag)
    {
        try
        {
            // 谨慎:尽量不要在业务层捕捉异常并处理
            throw new SQLException("发生异常了..");
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }
    return rows;
}

  推荐:在业务层统一抛出异常,然后在控制层统一处理。

02-13 17:05