Spring 事务失效的一种情况

service 代码

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Override
    public void multiUpdateUser(User user1, User user2) {
        this.updateUser(user1);
    }

    @Override
    @Transactional
    public void updateUser(User user) {
        int count = userMapper.updateByPrimaryKeySelective(user);
        System.out.println(count);
        int i = 1 / 0;
    }
}

问题:controller 里面调用 multiUpdateUser() 方法,则updateUser 方法的事务失效(即使出现异常也没有回滚),事务传播行为用的默认的 REQUIRED,即支持当前事务,如果没有事务就开启事务,这里却没有开启。
原因:
@Transactional 注解基于AOP实现,所以 updateUser() 被其他类调用时是通过代理对象来调用的,在代理对象的增强方法中开启事务,而没有注解的 multiUpdateUser() 方法被调用是原有的对象调用的,此时在 multiUpdateUser() 方法中调用 updateUser() 方法,则 updateUser() 就是直接被原有对象调用,而没有被代理对象调用,也就不会被增强,不会开启事务,即事务失效。
解决方案:
手动获取 Spring 中的代理对象(即 Spring 创建的 bean),通过代理对象去调用有事务注解的方法(本例updateUser() ),首先创建工具类,通过 ApplicationContex 获取 bean

/**
SpringUtils 工具类
*/
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

@Component
public class SpringUtils implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        if (SpringUtils.applicationContext == null) {
            SpringUtils.applicationContext = applicationContext;
        }
    }

    /**
     * 通过 class 获取 Bean
      */
    public static  T getBean(Class clazz) {
        return SpringUtils.applicationContext.getBean(clazz);
    }
}

service 中的代码改造如下

public void multiUpdateUser(User user1, User user2) {
        SpringUtils.getBean(UserService.class).updateUser(user1);
    }

至此,事务就生效了。

你可能感兴趣的:(Spring 事务失效的一种情况)