Java 当存在多个保存时,Spring数据和@Transactional不会回滚
我使用:Java 当存在多个保存时,Spring数据和@Transactional不会回滚,java,spring,hibernate,spring-data,hikaricp,Java,Spring,Hibernate,Spring Data,Hikaricp,我使用: 弹簧数据(4.x) 希卡里普 Hibernate(我使用EntityManager) 考虑以下存储库: public interface TestModelRepository extends JpaRepository<TestModel, Long> { } public interface TestModelRepository2 extends JpaRepository<TestModel2, Long> { } 存储库2中的第二个存储抛出Da
- 弹簧数据(4.x)
- 希卡里普
- Hibernate(我使用EntityManager)
public interface TestModelRepository extends JpaRepository<TestModel, Long> {
}
public interface TestModelRepository2 extends JpaRepository<TestModel2, Long> {
}
存储库2中的第二个存储抛出DataIntegrityViolationException,因为提供的值不是唯一的。事务应该回滚此方法中的所有内容,因为它是用@Transactional注释的,而不是
TestModel和TestModel2中的一个被持久化。实际上,它们在每次save()调用之后都会被持久化到数据库中,因此即使@Transactional方法尚未完成,这些值也会被插入到数据库中(我通过放置断点并登录到数据库进行了验证)。在我看来,autocommit设置为true,而我将其设置为false(在HikariCP配置中)
以下是我基于java的配置(片段):
主要问题:为什么事务不回滚所有内容?
其他问题:
- 什么时候应该将数据提交到数据库?交易何时提交或何时提交李>
是在整个事务过程中保持的连接,还是可以在事务中间返回到池中,如果需要的话,还需要另一个连接? - Spring数据在存储库上不需要@Transactional,那么事务参数是什么(传播和隔离)
自动提交
。我还注意到您正在使用mysql。确保您的模式和表是InnoDB而不是Myisamy表是MyISAM,将它们设置为InnoDB立即解决了问题!非常感谢你!如果你愿意,发布一个答案,我可以将其标记为已接受。干杯!很高兴它有帮助。这是InnoDB isue。我的表在MyISAM中,此引擎不支持事务。再次感谢!需要注意的是:连接自动提交是一个麻烦事——当执行使用@Transactional
声明的事务时,Spring会保存连接自动提交标志,将其设置为false,执行事务并恢复标志
@Service
static class Svc {
@Autowired
private TestModelRepository modelRepository;
@Autowired
private TestModelRepository2 modelRepository2;
@Transactional
public void insertWithException() {
assertThat(TransactionAspectSupport.currentTransactionStatus()).isNotNull();
modelRepository.save(new TestModel("any"));
modelRepository2.save(new TestModel2("unique"));
modelRepository2.save(new TestModel2("unique"));
}
}
@Bean
PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory);
return transactionManager;
}
@Bean
JpaVendorAdapter vendorAdapter() {
HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
adapter.setDatabase(Database.MYSQL);
adapter.setDatabasePlatform(MySQL5Dialect.class.getName());
return adapter;
}
LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean();
entityManagerFactory.setDataSource(dataSource);
entityManagerFactory.setJpaVendorAdapter(vendorAdapter);
entityManagerFactory.setPackagesToScan(packagesToScan);
entityManagerFactory.setJpaProperties(properties);