【问题标题】:Spring Data, Hibernate, Transactions and rolling back on exceptionsSpring Data、Hibernate、Transactions 和回滚异常
【发布时间】:2018-07-24 05:21:06
【问题描述】:

我有两个仓库:

  • 位置存储库
  • 播放器存储库

考虑以下情况:

@Transactional
public Player createPlayer(String locationName, String name) {
    Location location = new Location(locationName);
    location = locationRepository.save(location);

    Player player = new Player(name, location);
    return playerRepository.save(player);
}

玩家实体存在约束违规。我得到:org.springframework.dao.DataIntegrityViolationException

之后,我检查了数据库:

  • 未创建播放器
  • 位置已创建

此方法使用@Transaction 进行注释。那么为什么位置没有回滚呢?我期待这两个都不会在异常时保存到数据库中。如何回滚位置?

编辑:

@Bean
LocalContainerEntityManagerFactoryBean entityManagerFactory(JpaVendorAdapter adapter) {
    ...

    LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean();
    entityManagerFactory.setDataSource(dataSource);
    entityManagerFactory.setJpaVendorAdapter(adapter);
    entityManagerFactory.setPackagesToScan(packagesToScan);
    entityManagerFactory.setJpaProperties(properties);

    return entityManagerFactory;
}

@Bean
PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) 
{
    JpaTransactionManager transactionManager = new JpaTransactionManager();
    transactionManager.setEntityManagerFactory(entityManagerFactory);
    return transactionManager;
}

@Bean
PersistenceAnnotationBeanPostProcessor persistenceAnnotationBeanPostProcessor() {
    return new PersistenceAnnotationBeanPostProcessor();
}

@Bean
JpaVendorAdapter createVendorAdapter() {
    HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
    adapter.setDatabase(Database.MYSQL);
    adapter.setDatabasePlatform(MySQL5Dialect.class.getName());

    return adapter;
}

编辑:

有趣的是,该条目在此调用之后被持久化到数据库中:

location = locationRepository.save(location);

我在这个调用之后设置了一个断点并检查了数据库。条目被立即插入。

【问题讨论】:

  • 您是否在应用程序上下文中正确设置了事务管理器?什么样的类(服务、控制器...)包含createPlayer 方法?您使用基于 Java 或 XML 的 Spring 配置吗?
  • 您的连接是否配置了 autocommit=false?
  • 我已经用我的配置示例更新了这个问题。 createPlayer 只是用@Service 注释的普通类。我不确定在哪里设置自动提交,它应该是真还是假?

标签: java spring hibernate transactions spring-data


【解决方案1】:

为了让事务回滚数据库,需要 MySQL5InnoDBDialect。这将引擎从 engine=MyISAM 更改为 engine=InnoDB。 InnoDB 表模式支持事务。

我修改了我的 spring boot 2.0 application.properties 文件并添加了以下内容:

spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect

【讨论】:

    【解决方案2】:

    问题出在 MySQL 上。我不知道 MyISAM 不支持事务。

    【讨论】:

      【解决方案3】:

      如果你的 spring 配置设置正确,@Transactional 应该在基于 Spring 的事务管理的情况下工作。如果它仍然不起作用,那么您可以通过添加以下代码行以编程方式回滚 catch 块中的事务-

      TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();

      另外,你为@Transactional使用的导入,确保它是-

      导入 org.springframework.transaction.annotation.Transactional

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-05-03
        • 1970-01-01
        • 2015-06-19
        • 2015-02-12
        • 1970-01-01
        • 2015-03-21
        • 2020-03-10
        • 1970-01-01
        相关资源
        最近更新 更多