【问题标题】:Spring Data and @Transactional does not rollback when there are multiple savesSpring Data 和 @Transactional 在有多个保存时不会回滚
【发布时间】:2018-07-25 09:05:39
【问题描述】:

我用:

  • 弹簧数据 (4.x)
  • HikariCP
  • 休眠(我使用 EntityManager)

考虑以下存储库:

public interface TestModelRepository extends JpaRepository<TestModel, Long> {
}

public interface TestModelRepository2 extends JpaRepository<TestModel2, Long> {
}

以及以下服务:

@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"));
    }

}

存储库 2 中的第二次保存会引发 DataIntegrityViolationException,因为提供的值不是唯一的。事务应该回滚此方法中的所有内容,因为它使用@Transactional 注释,但它没有。

TestModel 和 TestModel2 之一被持久化。实际上,它们在每次 save() 调用之后就被持久化到数据库中,因此即使 @Transactional 方法尚未完成,这些值也会插入到数据库中(我通过放置断点并登录到数据库来验证它)。在我看来,自动提交设置为 true,但我将其设置为 false(在 HikariCP 配置中)。

这是我基于 java 的配置(片段):

@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);

主要问题:为什么事务不回滚所有内容?

其他问题:

  • 何时应将数据提交到数据库?何时提交事务或任何时间?
  • 是在整个事务过程中保持连接,还是可以在事务过程中将其返回到池中,如果需要,再请求另一个连接?
  • Spring Data 不需要在存储库上使用 @Transactional,那么事务参数是什么(传播和隔离)?

【问题讨论】:

  • 您可能在连接或数据库配置中有autocommit。我还注意到您正在使用 mysql。确保您的架构和表是 InnoDB 而不是 MyISAM
  • 我的表是 MyISAM,将它们设置为 InnoDB 立即解决了问题!太感谢了!如果您愿意,请发布答案,我可以将其标记为已接受。
  • 干杯!很高兴它有帮助。

标签: java spring hibernate spring-data hikaricp


【解决方案1】:

您可能在连接或数据库配置中具有自动提交功能。我还注意到您正在使用 mysql。确保您的架构和表是 InnoDB 而不是 MyISAM

【讨论】:

  • 这是 InnoDB 问题。我的表在 MyISAM 中,这个引擎不支持事务。再次感谢!
  • 注意:连接自动提交是一个红鲱鱼 - 当执行使用@Transactional 声明的事务时,springs 保存连接自动提交标志,将其设置为 false,执行事务,然后恢复标志
猜你喜欢
  • 2013-09-16
  • 2017-04-14
  • 1970-01-01
  • 1970-01-01
  • 2018-11-08
  • 2023-03-13
  • 2018-09-27
  • 2016-12-11
  • 2019-06-30
相关资源
最近更新 更多