消息关闭
    暂无新消息!
    今天尝试事务回滚的时候遇到一个问题:
    我在controller中try一个方法,该方法执行一条插入语句,带有@Transactional注解,并会抛出一个异常。controller中catch这个异常之后,从控制台输出插入的内容
    我感觉应该是插入语句回滚,内容被删除,然而结果是:数据库确实回滚了,也确实输出了被插入的内容。
    想问问大神,这是什么原理?
controller:
@RequestMapping("/regist")
public ModelAndView regist(HttpServletRequest request, User user) throws Exception {
if (checkParams(new String[] { user.getUsername(), user.getPassword() })) {
//TODO @Transaction check if the account has already exist
try {
userService.saveUser(user);
} catch (Exception e) {
// TODO Auto-generated catch block
System.out.println("regist"+e.getMessage());
request.setAttribute("describe", e.getMessage());
}
request.setAttribute("username", user.getUsername());
request.setAttribute("password", user.getPassword());
System.out.println(user);
return new ModelAndView("succ");
}
return new ModelAndView("regist");
}

service:
@Transactional(rollbackFor = Exception.class)
public void saveUser(User user) throws Exception {
if (user != null && user.getId() != null) {
userDao.updateUser(user);
} else {
// TODO find if there is a repetition, can also use SQL
try {
List<User> allUser = userDao.getUser();
userDao.insertUser(user);
for (User _user : allUser) {
if (_user.getUsername().equals(user.getUsername()))
throw new Exception("The account is exist!");
}
} catch (Exception e) {
throw e;
}
}
}

控制台输出结果:
User [userid=1, username=1, password=1]
registThe account is exist!
User [userid=2, username=1, password=2]
数据库:

8个回答

︿ 2
service 方法在捕获到 RuntimeException 及其子类的异常时才会回滚吧
︿ 1
spring默认事务只在发生未被捕获的 runtimeexcetpion时才回滚,你的saveUser(user)方法被你try...catch了,所以无法回滚,
可以选择去掉try...catch

@Transactional(rollbackFor = Exception.class)
    public void saveUser(User user) throws Exception {
        if (user != null && user.getId() != null) {
            userDao.updateUser(user);
        } else {
            // TODO find if there is a repetition, can also use SQL
     
                List<User> allUser = userDao.getUser();
                userDao.insertUser(user);
                for (User _user : allUser) {
                    if (_user.getUsername().equals(user.getUsername()))
                        throw new Exception("The account is exist!");
                } 
        }
    }

或者在catch加上TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();

@Transactional(rollbackFor = Exception.class)
    public void saveUser(User user) throws Exception {
        if (user != null && user.getId() != null) {
            userDao.updateUser(user);
        } else {
            // TODO find if there is a repetition, can also use SQL
            try {
                List<User> allUser = userDao.getUser();
                userDao.insertUser(user);
                for (User _user : allUser) {
                    if (_user.getUsername().equals(user.getUsername()))
                        throw new Exception("The account is exist!");
                }
            } catch (Exception e) {
                  TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                throw e;
            }
        }
    }
︿ 0
好像sping管理事务的时候在service层不能捕获异常,你捕获了异常就不能回滚,你把throw e抛出异常那句去掉的话事务应就该不会回滚的
︿ 0
spring的实务配置会在抛出RuntimeException的时候回滚,在你多次往数据库操作的时候,只有全部成功的时候才会顺利通过,不然的话就会全部回滚,个人理解是这样的。