【发布时间】:2020-10-18 04:20:59
【问题描述】:
当使用@Transactional(rollbackFor) 引发检查的异常时,我一直坚持让 Spring 回滚事务。这是我的代码:
数据访问类:
@Repository
public class CustomerDao {
@Autowired
private SessionFactory sessionFactory;
public void willRollback() throws CheckedException {
sessionFactory.getCurrentSession().persist(new SpringCustomer(null, "roll back"));
throw new CheckedException();
}
}
CheckedException 只是一个简单的检查异常:
public class CheckedException extends Exception {}
服务类CustomerService:
@Service
public class CustomerService {
@Autowired
private CustomerDao customerDao;
@Transactional(transactionManager = "hibernateTransactionManager", rollbackFor = CheckedException.class)
public void willRollback() throws CheckedException {
customerDao.willRollback();
}
}
Beans 配置:
@Configuration
public class BasicConfig {
@Bean
public DataSource dataSource() {
DriverManagerDataSource ds = new DriverManagerDataSource();
ds.setDriverClassName("com.mysql.cj.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/test_hibernate?useSSL=false");
ds.setUsername("root");
ds.setPassword("Passw0rd");
return ds;
}
@Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean localSessionFactoryBean = new LocalSessionFactoryBean();
localSessionFactoryBean.setDataSource(dataSource());
localSessionFactoryBean.setPackagesToScan("com.home.exception.checked");
Properties hibernateProperties = new Properties();
hibernateProperties.put("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");
hibernateProperties.put("hibernate.show_sql", "true");
hibernateProperties.put("hibernate.hbm2ddl.auto", "update");
localSessionFactoryBean.setHibernateProperties(hibernateProperties);
return localSessionFactoryBean;
}
@Bean
public HibernateTransactionManager hibernateTransactionManager() {
return new HibernateTransactionManager(sessionFactory().getObject());
}
}
最后,这是我的主要课程:
@Configuration
@ComponentScan
@EnableTransactionManagement
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx =
new AnnotationConfigApplicationContext(Main.class);
try {
ctx.getBean(CustomerService.class).willRollback();
} catch (CheckedException e) {
e.printStackTrace();
}
ctx.close();
}
}
我已经阅读了许多与这些问题相关的答案,所有答案都建议从代理本身外部调用事务方法,我这样做了。无论如何,实体总是被持久化在数据库中并且事务不会回滚。
任何帮助将不胜感激。
更新: 根据@kavithakaran-kanapathippillai 的回答,我调试了TransactionAspectSupport.completeTransactionAfterThrowing() 方法以及以下方法,发现执行了回滚逻辑。但是,当查询数据库时,实体仍然出现。
因此,我启用了 db logging 以查看正在运行的查询,我发现了以下内容:
2020-06-28T07:29:48.516038Z 391 Query SET autocommit=0
2020-06-28T07:29:48.520253Z 391 Query insert into spring_customer (name) values ('roll back')
2020-06-28T07:29:48.524969Z 391 Query rollback
2020-06-28T07:29:48.526026Z 391 Query SET autocommit=1
我不知道为什么会发生这种情况,但看起来 Spring 回滚工作正常。
UPDATE2:问题是由于我的表使用的是 MyISAM 引擎(非事务性引擎)。一旦我将其更改为 InnoDB(事务引擎),记录就不再持久化了。
【问题讨论】:
标签: mysql transactions spring-data