当存在多个保存时,Spring Data和@Transactional不会回滚

时间:2018-02-14 17:37:35

标签: java spring hibernate spring-data hikaricp

我用:

  • Spring数据(4.x)
  • HikariCP
  • 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方法尚未完成(即我通过放置断点并登录到数据库来验证它),值也会插入到数据库中。在我看来,autocommit设置为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,那么事务参数是什么(传播和隔离)?

1 个答案:

答案 0 :(得分:1)

您可能已在连接或db config中进行自动提交。我也注意到你正在使用mysql。确保您的架构和表格是InnoDB而不是MyISAM