@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout=36000, rollbackFor=Exception.class) public void test(){ List<InfoCompanyUser> list = new ArrayList<InfoCompanyUser>(); InfoCompanyUser u = new InfoCompanyUser(); u.setUsername("68112710000"); u.setStatus(1); list.add(u); u = new InfoCompanyUser(); u.setUsername("68112710001"); u.setStatus(1); list.add(u); u = new InfoCompanyUser(); u.setUsername("68112710002"); u.setStatus(1); list.add(u); infoCompanyUserMapper.updateBatch(list); //throw new RuntimeException("测试插入事务"); int i = 1/0; } public void insertTest(){ // aop拦截在service层,需要调用其内部方法时, 直接调用无法拦截aop内部调用,所以需要设置其代理,此时调用内部即可拦截 getService().test(); //getService1().test(); //throw new RuntimeException("测试插入事务"); int i = 1/0; }
当service中的某个没标注@Transactional的方法调用另一个标注了@Transactional的方法时,没开启事务
@Transactional其实就是一个aop代理,是一个cglib动态代理
原因:调用内部方法时候,指向目标对象,不会执行切面事务,而调用标注@Transactional的方法时,使用的是代理对象,执行了切面事务
解决方法
/**
* 方案一--从beanFactory中获取对象
*
* @Author: wpf
* @Date: 15:00 2018/5/31
* @Description:
* @param * @param null
* @return
*/
private RemoteAuditService getService(){
return SpringContextUtil.getBean(this.getClass());
}
/**
* 方案二--获取代理对象
*
* @Author: wpf
* @Date: 15:00 2018/5/31
* @Description:
* @param * @param null
* @return
*/
private RemoteAuditService getService1(){
// 采取这种方式的话, 注解到类上即可
//@EnableAspectJAutoProxy(exposeProxy=true,proxyTargetClass=true)
//必须设置为true
return AopContext.currentProxy() != null? (RemoteAuditService)AopContext.currentProxy() : this;
}
@Component
public class SpringContextUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext = null;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if(SpringContextUtil.applicationContext == null){
SpringContextUtil.applicationContext = applicationContext;
}
}
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
public static Object getBean(String name){
return getApplicationContext().getBean(name);
}
public static <T> T getBean(Class<T> clazz){
return getApplicationContext().getBean(clazz);
}
}
参考:https://blog.youkuaiyun.com/dream_broken/article/details/72911148