java - Spring Data和@Transactional在多次保存时不回滚

标签 java spring hibernate spring-data hikaricp

我使用:

  • Spring 数据 (4.x)
  • 光CP
  • Hibernate(我使用 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,那么事务参数是什么(传播和隔离)?

最佳答案

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

关于java - Spring Data和@Transactional在多次保存时不回滚,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48793163/

相关文章:

Java:如何将控制台输出镜像到文件

Java Tomcat 8.5/Spring 4 从 URL 中移除多个空格

java - Web 服务器上的 Zip 文件以解压到本地计算机

java - 从多对多关系返回值

java - Spring mvc 异常中的 servlet 名称为空

java - 如何配置 spring-boot 项目与内存空间数据库一起进行测试?

java - hibernate + PostgreSQL : Null boolean value being returned as 'true'

hibernate - 为 tomcat 配置 hibernate JNDI 的挑战

java - 使用 spring hibernate 从序列中获取下一个值

带有 Jersey 和 ActiveMQ 的 Java RESTful 服务 - 在启动时加载到 ActiveMQ 的连接