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> T getBean(Class<T> clazz) {
return SpringUtils.applicationContext.getBean(clazz);
}
}
service 中的代码改造如下
public void multiUpdateUser(User user1, User user2) {
SpringUtils.getBean(UserService.class).updateUser(user1);
}
至此,事务就生效了。
网友评论