简体   繁体   English

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

[英]Spring Data and @Transactional does not rollback when there are multiple saves

I use:我用:

  • Spring data (4.x)弹簧数据 (4.x)
  • HikariCP HikariCP
  • Hibernate (I use EntityManager)休眠(我使用 EntityManager)

Consider the following repositories:考虑以下存储库:

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

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

and the following service:以及以下服务:

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

}

The second save in repository 2 throws DataIntegrityViolationException because the provided value is not unique.存储库 2 中的第二个保存抛出 DataIntegrityViolationException,因为提供的值不是唯一的。 Transaction should rollback everything in this method as it is annotated with @Transactional, hovewer it does not.事务应该回滚此方法中的所有内容,因为它是用@Transactional 注释的,但是它没有。

TestModel and one of TestModel2 are persisted. TestModel 和 TestModel2 之一被持久化。 Actually they are persisted to the database just after each save() call, so the values are inserted into the database even if the @Transactional method did not complete yet (I verified it by placing a breakpoint and logging into the database).实际上,它们在每次 save() 调用后都被持久化到数据库中,因此即使 @Transactional 方法尚未完成,这些值也会插入到数据库中(我通过放置断点并登录到数据库来验证它)。 It looks to me like autocommit is set to true, hovewer I set it to false (in HikariCP config).在我看来,自动提交设置为 true,但我将其设置为 false(在 HikariCP 配置中)。

Here is my java-based configuration (fragments):这是我的基于 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);

Main question: why the transaction does not rollback everything?主要问题:为什么事务不回滚一切?

Additional questions:补充问题:

  • when the data should be commited to the database?什么时候应该将数据提交到数据库? When the transaction is commited or anytime?事务何时提交或何时提交?
  • is the connection kept during the whole transaction, or can it be returned to the pool in the middle of transaction and then another connection is requested if needed?连接是在整个事务期间保持,还是可以在事务中间返回到池中,然后在需要时请求另一个连接?
  • Spring Data doesn't require @Transactional on repositories, what are the transaction parameters then (propagation and isolation)? Spring Data 在存储库上不需要 @Transactional,那么事务参数是什么(传播和隔离)?

You may have autocommit on the connection or in the db config.您可能在连接或数据库配置中自动提交。 I also noticed you're using mysql.我还注意到您正在使用 mysql。 Make sure your schema and tables are InnoDB not MyISAM确保您的架构和表是 InnoDB 而不是 MyISAM

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM