解决try-catch捕获异常信息后Spring事务失效的问题,需要做以下几个步骤:
1. 开启对事务的支持
将事务注解开启,可以使用在类或方法级别上使用事务注解:
@Configuration
@EnableTransactionManagement
public class AppConfig {
// ...
}
2. 设置事务传播属性
使用@Transactional注解标记需要开启事务的方法,并设置事务传播属性,以便将异常抛出给上层调用:
@Transactional(propagation=Propagation.REQUIRES_NEW, rollbackFor=Exception.class)
public void saveUser(User user) throws Exception {
// do something
}
其中, Propagation.REQUIRES_NEW
表示事务进行到该方法时,将新开启一个事务,与之前的事务无关。 rollbackFor
表示将指定异常类型加入回滚策略中,当遇到此类型异常时,将进行事务回滚。
3. 不捕获异常或将异常包装再抛出
由于Spring事务是通过AOP实现的,当方法执行抛出异常时,AOP会将异常信息“包装”并抛出到上层调用。因此,如果捕获了异常并处理掉,就会使得事务管理器无法感知到异常,导致事务失效。
所以,要么不捕获异常并让外层try-catch捕获并处理;要么捕获并将异常包装再抛出,以便外层try-catch能够感知到异常:
@Transactional(propagation=Propagation.REQUIRES_NEW, rollbackFor=Exception.class)
public void saveUser(User user) throws Exception {
try {
// do something
} catch (Exception e) {
throw new RuntimeException(e);
}
}
上面的代码将异常进行“包装”再抛出,这样外层try-catch就能够感知到异常并进行处理了,而且事务也能够得到正常的回滚。
示例说明
下面以一个简单的示例来说明以上攻略的使用方法:
@Service
public class UserService {
@Autowired
private UserDao userDao;
@Transactional(propagation=Propagation.REQUIRES_NEW, rollbackFor=Exception.class)
public void saveUser(User user) throws Exception {
userDao.save(user);
throw new RuntimeException("Exception has occurred!");
}
}
@RestController
public class UserController {
@Autowired
private UserService userService;
@PostMapping("/user")
public String saveUser() {
try {
User user = new User();
user.setName("张三");
user.setAge(18);
userService.saveUser(user);
} catch (Exception e) {
e.printStackTrace();
}
return "User saved.";
}
}
上面代码中,UserService的saveUser方法向数据库保存一个用户信息,然后故意抛出了一个RuntimeException异常。UserController的saveUser方法调用了UserService的saveUser方法,在外层进行了try-catch处理,同时返回了"User saved."字符串。
如果没有正确的设置@Transactional注解属性和抛出“包装”后的异常,那么程序在执行完saveUser方法后,仍会返回"User saved."字符串,并且数据库中也会存在刚才保存的用户信息,就证明了事务失效的问题。
但如果正确的设置@Transactional注解和抛出“包装”后的异常,那么程序在执行完saveUser方法后会抛出RuntimeException异常,UserController的saveUser方法就会捕获到该异常并打印异常信息,返回值也不再是"User saved."字符串,数据库中也不会保存刚才的用户信息,就证明了事务得到了正常的回滚。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:解决try-catch捕获异常信息后Spring事务失效的问题 - Python技术站