1.先说说在使用这个注解的时候遇到的问题吧!!!
在学习Spring transaction的时候想要实现遇到报错然后回滚,结果总是回滚失败!!最后请求大佬支援看到了我的傻逼问题
我先说说我的傻逼问题,我把@Configuration写成了@Configurable 然后在代码中使用的是:
@Configurable//这是错误的 应该改成@Configuration(proxyBeanMethod = false)
@ComponentScan("com.youshang520i")
@EnableTransactionManagement
@MapperScan("com.youshang520i.dao")
public class AppTx {
@Bean(destroyMethod = "close")
private DataSource dataSource(){
BasicDataSource pool = new BasicDataSource();
pool.setUsername("****");
pool.setPassword("*****");
pool.setDriverClassName("com.mysql.cj.jdbc.Driver");
pool.setUrl("jdbc:mysql://****.***.***.***:***/test?useUnicode=true&characterEncoding=utf-8");
return pool;
}
@Bean
public SqlSessionFactory sqlSessionFactory() throws Exception {//DataSource dataSource
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(this.dataSource());
return sqlSessionFactoryBean.getObject();
}
@Bean
public TransactionManager transactionManager(){//DataSource dataSource
return new DataSourceTransactionManager(this.dataSource());
}
}
2. 导致事务一直不会回滚,代码检查了很多遍配置也看了一两遍,死都不会想到我把@Configuration写成了@Configurable然后去查看源码(现在是在@Configurable注解下调试)
在源码org.springframework.transaction.interceptor.TransactionAspectSupport#invokeWithinTransaction 中看到了回滚的时候这个方法被调用了两次
第一次的时候执行了TeacherService.insert,最终执行了StudentService.insert 对StudentService上的@Transactional事务进行了回滚,按照正常的来说已经实现了Spring的@Transactional的回滚
下面是StudentServiceImpl和TeacherServiceImpl的代码
@Override
@Transactional(propagation = Propagation.REQUIRED)
public boolean insert(StudentModel studentModel) {
// Object savePoint = TransactionAspectSupport.currentTransactionStatus().createSavepoint();
int insert = 0;
try {
insert = studentDao.insert(studentModel);
// insert = studentDao.insert(studentModel);
TeacherModel teacherModel = new TeacherModel();
teacherModel.setTid(1);
teacherModel.setSid(studentModel.getId());
teacherModel.setTname("m ~");
insert = teacherService.insert(teacherModel);
} catch (Exception e) {
// System.out.println("发生异常,进行手动回滚!");
// TransactionAspectSupport.currentTransactionStatus().rollbackToSavepoint(savePoint);
// TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
e.printStackTrace();
throw new RuntimeException();
}
return insert > 0;
}
@Override
@Transactional(rollbackFor = SQLException.class)//(propagation= Propagation.REQUIRED, rollbackFor = Exception.class)
public int insert(TeacherModel teacherModel) {
return teacherDao.insert(teacherModel);
}
上面代码两段代码是没问题的
原因有可能是因为@Configuration(proxyBeanMethods = false)
proxyBeanMethods = false //设置lite模式
没办法保证是一个实例,在mysql触发事务回滚的时候提交的实例和回滚的实例不是同一个导致回滚失败
解决方案:
使用proxyBeanMethod = true // 设置 full模式
设置full模式可以保证创建出来的bean是在同一个实例中