需求
在service层的某个方法中,在执行完一个对数据库的写方法后,抛出异常,再执行另一个对数据库的写方法,伪代码如下:
@Transactional
public void func() {
dao.write(pojo1);
throw new Exception("异常");
dao.write(pojo2);
}
要求此时事务全部回滚,即pojo1和pojo2都不写进数据库。
单元测试代码
@Test
public void testTransactional() {
User user = new User();
user.setUid(9);
user.setUsername("李四");
user.setPassword("234");
userService.createAndUpdate(user);
}
不回滚写法
这种写法保留了createUser方法对数据库的写操作,而不执行UpdateUser方法,结果是把创建的User对象李四写进了数据库,但并没有重命名为admin。原因是抛出异常并捕获后,并没有触发事务回滚。所以代码结束后李四保留在了数据库中。
@Override
public void createAndUpdate(User user) {
try {
createUser(user);
if (!user.getPassword().equals("123")) {
throw new RuntimeException("密码不是123");
}
user.setUsername("admin");
updateUser(user);
} catch (Exception e) {
e.printStackTrace();
}
}
回滚写法
写法一:方法抛异常
这种写法可以在方法处抛出异常,也可以不抛出(throws RuntimeException可写可不写)。
@Override
public void createAndUpdate(User user) throws RuntimeException {
createUser(user);
if (!user.getPassword().equals("123")) {
throw new RuntimeException("密码不是123");
}
user.setUsername("admin");
updateUser(user);
}
写法二:try catch捕获异常
这种方法相比于不回滚的那种写法,只是在catch作用域内多加入了一行代码:
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
完整方法:
@Override
public void createAndUpdate(User user) {
try {
createUser(user);
if (!user.getPassword().equals("123")) {
throw new RuntimeException("密码不是123");
}
user.setUsername("admin");
updateUser(user);
} catch (Exception e) {
e.printStackTrace();
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
}
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/19599.html