@Transactional如何对分布式事务生效
说明:介绍 @Transactional
对分布式事务生效的一种情况
场景
如下,该方法根据主键删除用户,同时,调用其他服务的 API 删除该用户所拥有的角色记录。方法涉及多个服务数据库操作,需考虑分布式事务。
@Overridepublic void delete3(Long id) {// 根据主键删除用户(本服务)userMapper.deleteById(id);// 调用 roleAPI 删除该用户所拥有的角色(其他服务)roleApi.deleteRoleByUserId(id);}
直接在方法上加 @Transactional
注解,@Transactional 是本地事务注解,只能控制本服务,跨服务的事务是不生效的。
@Transactional@Overridepublic void delete3(Long id) {// 根据主键删除用户(本服务)userMapper.deleteById(id);// 调用 roleAPI 删除该用户所拥有的角色(其他服务)roleApi.deleteRoleByUserId(id);}
试试看,在其他服务操作这里,手动制造异常
@Overridepublic void deleteRoleByUserId(Long id) {// 模拟异常int i = 1 / 0;roleMapper.deleteRoleByUserId(id);}
调用接口,执行该方法(删除 userId=142 的记录),可见用户被删除,但该用户对应的角色未被删除
但是
有一种情况,可使 @Transactional 注解对以上场景的分布式事务生效,即在其他服务发生异常的同时,使调用方也抛出异常,只要抛出异常被框架捕获,@Transactional 就能回滚本地事务。
怎么做呢?只需要让调用方执行完后返回 Boolean
@Overridepublic Boolean deleteRoleByUserId(Long id) {// 模拟异常int i = 1 / 0;roleMapper.deleteRoleByUserId(id);return Boolean.TRUE;}
当方法发生异常时,抛出的异常无法封装到 Boolean 类型中,会让调用方抛出实例化异常,这样会迫使调用方回滚本地事务。
(被调用方抛出算数异常)
(调用方抛出解码异常)
导致本地事务被回滚
最后
以上代码在 yudao 框架中实验