小编典典

在Spring @Transactional内部启用JPA保存且多个实体不会回滚,并启用了Exception.class的回滚

spring-boot

我已经呆了好几个小时了,当我将实体保存在封装事务中时,我找不到一种自动解决JPARepository自动启动/提交事务的方法。

我总共创建了3个实体。第2,第ClientAdminCreditPot将被制成,以便所述第三时Institution实体制成,该实体可以形成被持续之前的关系。

当抛出一个异常时,我希望它可以使创建的实体不被提交(即整个过程回滚)。

此刻,我在日志中看到JPA Save方法 可能会
启动其自己的事务(我不完全了解日志),这会导致已调用的实体repo.save(entity)在其自己的事务中提交?

任何帮助将不胜感激。

    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
public void createInstitution(InstitutionSignUpForm form) throws Exception {

    //Create Admin account.
    ClientAdmin clientAdmin = new ClientAdmin();
    clientAdmin.setRole(roleRepo.findOneByRole("SUPER_ADMIN").orElseThrow(() -> new Exception("Can not resolve role SUPER_ADMIN")));
    clientAdmin.setPassword(passwordEncoder.encode(form.getPassword()));
    clientAdmin.setUsername(form.getUsername());
    clientAdmin = clientAdminRepo.save(clientAdmin);

    //Create Credit Pot for institution.
    CreditPot creditPot = new CreditPot();
    creditPot.setIsPrimaryPot(true);
    creditPot.setName("Primary Credit Pot");
    creditPot.setCredits(300L);
    creditPot = creditPotRepo.save(creditPot);

    System.out.println("Throwing Exception.");
    if(1==1) throw new Exception("!!!", new Throwable("!!!"));

    //Create institution and assign relationships.
    Institution institution = new Institution();
    institution.setDiceCode(dicewareGenerator.generateRandomPassword(6));
    institution.setName(form.getInstitutionName());
    institution.setPrimaryCreditPot(creditPot);
    clientAdmin.setInstitution(institution);
    institutionRepo.saveAndFlush(institution);
}

日志:

    2019-09-12 10:46:41.148 DEBUG 24621 --- [nio-5000-exec-6] o.j.s.OpenEntityManagerInViewInterceptor : Opening JPA EntityManager in OpenEntityManagerInViewInterceptor
2019-09-12 10:46:41.148 TRACE 24621 --- [nio-5000-exec-6] .s.t.s.TransactionSynchronizationManager : Bound value [org.springframework.orm.jpa.EntityManagerHolder@5ed67928] for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@70286b92] to thread [http-nio-5000-exec-6]
2019-09-12 10:46:41.149 TRACE 24621 --- [nio-5000-exec-6] .s.t.s.TransactionSynchronizationManager : Retrieved value [org.springframework.orm.jpa.EntityManagerHolder@5ed67928] for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@70286b92] bound to thread [http-nio-5000-exec-6]
2019-09-12 10:46:41.149 DEBUG 24621 --- [nio-5000-exec-6] o.s.orm.jpa.JpaTransactionManager        : Found thread-bound EntityManager [SessionImpl(652375272<open>)] for JPA transaction
2019-09-12 10:46:41.149 DEBUG 24621 --- [nio-5000-exec-6] o.s.orm.jpa.JpaTransactionManager        : Creating new transaction with name [com.j3den.edu.webserver.services.sigup.InstitutionSignUpService.createInstitution]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,-java.lang.Exception
2019-09-12 10:46:41.150 DEBUG 24621 --- [nio-5000-exec-6] o.s.orm.jpa.JpaTransactionManager        : Exposing JPA transaction as JDBC [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@74972cba]
2019-09-12 10:46:41.150 TRACE 24621 --- [nio-5000-exec-6] .s.t.s.TransactionSynchronizationManager : Bound value [org.springframework.jdbc.datasource.ConnectionHolder@19e50439] for key [HikariDataSource (HikariPool-1)] to thread [http-nio-5000-exec-6]
2019-09-12 10:46:41.150 TRACE 24621 --- [nio-5000-exec-6] .s.t.s.TransactionSynchronizationManager : Initializing transaction synchronization
2019-09-12 10:46:41.150 TRACE 24621 --- [nio-5000-exec-6] o.s.t.i.TransactionInterceptor           : Getting transaction for [com.j3den.edu.webserver.services.sigup.InstitutionSignUpService.createInstitution]
2019-09-12 10:46:41.150 TRACE 24621 --- [nio-5000-exec-6] .s.t.s.TransactionSynchronizationManager : Bound value [org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$DefaultCrudMethodMetadata@304f1d77] for key [public abstract java.util.Optional com.j3den.edu.models.repos.RoleRepo.findOneByRole(java.lang.String)] to thread [http-nio-5000-exec-6]
2019-09-12 10:46:41.151 TRACE 24621 --- [nio-5000-exec-6] o.s.t.i.TransactionInterceptor           : No need to create transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.findOneByRole]: This method is not transactional.
2019-09-12 10:46:41.151 TRACE 24621 --- [nio-5000-exec-6] .s.t.s.TransactionSynchronizationManager : Retrieved value [org.springframework.orm.jpa.EntityManagerHolder@5ed67928] for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@70286b92] bound to thread [http-nio-5000-exec-6]
2019-09-12 10:46:41.151 TRACE 24621 --- [nio-5000-exec-6] .s.t.s.TransactionSynchronizationManager : Retrieved value [org.springframework.orm.jpa.EntityManagerHolder@5ed67928] for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@70286b92] bound to thread [http-nio-5000-exec-6]
2019-09-12 10:46:41.153 TRACE 24621 --- [nio-5000-exec-6] .s.t.s.TransactionSynchronizationManager : Removed value [org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$DefaultCrudMethodMetadata@304f1d77] for key [public abstract java.util.Optional com.j3den.edu.models.repos.RoleRepo.findOneByRole(java.lang.String)] from thread [http-nio-5000-exec-6]
2019-09-12 10:46:41.242 TRACE 24621 --- [nio-5000-exec-6] .s.t.s.TransactionSynchronizationManager : Bound value [org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$DefaultCrudMethodMetadata@2d5257a2] for key [public abstract java.lang.Object org.springframework.data.repository.CrudRepository.save(java.lang.Object)] to thread [http-nio-5000-exec-6]
2019-09-12 10:46:41.242 TRACE 24621 --- [nio-5000-exec-6] .s.t.s.TransactionSynchronizationManager : Retrieved value [org.springframework.orm.jpa.EntityManagerHolder@5ed67928] for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@70286b92] bound to thread [http-nio-5000-exec-6]
2019-09-12 10:46:41.242 DEBUG 24621 --- [nio-5000-exec-6] o.s.orm.jpa.JpaTransactionManager        : Found thread-bound EntityManager [SessionImpl(652375272<open>)] for JPA transaction
2019-09-12 10:46:41.242 TRACE 24621 --- [nio-5000-exec-6] .s.t.s.TransactionSynchronizationManager : Retrieved value [org.springframework.jdbc.datasource.ConnectionHolder@19e50439] for key [HikariDataSource (HikariPool-1)] bound to thread [http-nio-5000-exec-6]
2019-09-12 10:46:41.243 DEBUG 24621 --- [nio-5000-exec-6] o.s.orm.jpa.JpaTransactionManager        : Participating in existing transaction
2019-09-12 10:46:41.243 TRACE 24621 --- [nio-5000-exec-6] o.s.t.i.TransactionInterceptor           : Getting transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
2019-09-12 10:46:41.243 TRACE 24621 --- [nio-5000-exec-6] .s.t.s.TransactionSynchronizationManager : Retrieved value [org.springframework.orm.jpa.EntityManagerHolder@5ed67928] for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@70286b92] bound to thread [http-nio-5000-exec-6]
2019-09-12 10:46:41.244 TRACE 24621 --- [nio-5000-exec-6] o.s.t.i.TransactionInterceptor           : Completing transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
2019-09-12 10:46:41.245 TRACE 24621 --- [nio-5000-exec-6] .s.t.s.TransactionSynchronizationManager : Removed value [org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$DefaultCrudMethodMetadata@2d5257a2] for key [public abstract java.lang.Object org.springframework.data.repository.CrudRepository.save(java.lang.Object)] from thread [http-nio-5000-exec-6]
2019-09-12 10:46:41.245 TRACE 24621 --- [nio-5000-exec-6] .s.t.s.TransactionSynchronizationManager : Bound value [org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$DefaultCrudMethodMetadata@2d5257a2] for key [public abstract java.lang.Object org.springframework.data.repository.CrudRepository.save(java.lang.Object)] to thread [http-nio-5000-exec-6]
2019-09-12 10:46:41.245 TRACE 24621 --- [nio-5000-exec-6] .s.t.s.TransactionSynchronizationManager : Retrieved value [org.springframework.orm.jpa.EntityManagerHolder@5ed67928] for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@70286b92] bound to thread [http-nio-5000-exec-6]
2019-09-12 10:46:41.245 DEBUG 24621 --- [nio-5000-exec-6] o.s.orm.jpa.JpaTransactionManager        : Found thread-bound EntityManager [SessionImpl(652375272<open>)] for JPA transaction
2019-09-12 10:46:41.245 TRACE 24621 --- [nio-5000-exec-6] .s.t.s.TransactionSynchronizationManager : Retrieved value [org.springframework.jdbc.datasource.ConnectionHolder@19e50439] for key [HikariDataSource (HikariPool-1)] bound to thread [http-nio-5000-exec-6]
2019-09-12 10:46:41.245 DEBUG 24621 --- [nio-5000-exec-6] o.s.orm.jpa.JpaTransactionManager        : Participating in existing transaction
2019-09-12 10:46:41.245 TRACE 24621 --- [nio-5000-exec-6] o.s.t.i.TransactionInterceptor           : Getting transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
2019-09-12 10:46:41.245 TRACE 24621 --- [nio-5000-exec-6] .s.t.s.TransactionSynchronizationManager : Retrieved value [org.springframework.orm.jpa.EntityManagerHolder@5ed67928] for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@70286b92] bound to thread [http-nio-5000-exec-6]
2019-09-12 10:46:41.246 TRACE 24621 --- [nio-5000-exec-6] o.s.t.i.TransactionInterceptor           : Completing transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
2019-09-12 10:46:41.247 TRACE 24621 --- [nio-5000-exec-6] .s.t.s.TransactionSynchronizationManager : Removed value [org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$DefaultCrudMethodMetadata@2d5257a2] for key [public abstract java.lang.Object org.springframework.data.repository.CrudRepository.save(java.lang.Object)] from thread [http-nio-5000-exec-6]
Throwing Exception.
2019-09-12 10:46:41.247 TRACE 24621 --- [nio-5000-exec-6] o.s.t.i.TransactionInterceptor           : Completing transaction for [com.j3den.edu.webserver.services.sigup.InstitutionSignUpService.createInstitution] after exception: java.lang.Exception: !!!
2019-09-12 10:46:41.247 TRACE 24621 --- [nio-5000-exec-6] o.s.t.i.RuleBasedTransactionAttribute    : Applying rules to determine whether transaction should rollback on java.lang.Exception: !!!
2019-09-12 10:46:41.247 TRACE 24621 --- [nio-5000-exec-6] o.s.t.i.RuleBasedTransactionAttribute    : Winning rollback rule is: RollbackRuleAttribute with pattern [java.lang.Exception]
2019-09-12 10:46:41.247 DEBUG 24621 --- [nio-5000-exec-6] o.s.orm.jpa.JpaTransactionManager        : Initiating transaction rollback
2019-09-12 10:46:41.247 DEBUG 24621 --- [nio-5000-exec-6] o.s.orm.jpa.JpaTransactionManager        : Rolling back JPA transaction on EntityManager [SessionImpl(652375272<open>)]
2019-09-12 10:46:41.248 TRACE 24621 --- [nio-5000-exec-6] .s.t.s.TransactionSynchronizationManager : Clearing transaction synchronization
2019-09-12 10:46:41.248 TRACE 24621 --- [nio-5000-exec-6] .s.t.s.TransactionSynchronizationManager : Removed value [org.springframework.jdbc.datasource.ConnectionHolder@19e50439] for key [HikariDataSource (HikariPool-1)] from thread [http-nio-5000-exec-6]
2019-09-12 10:46:41.248 DEBUG 24621 --- [nio-5000-exec-6] o.s.orm.jpa.JpaTransactionManager        : Not closing pre-bound JPA EntityManager after transaction
2019-09-12 10:46:41.248 TRACE 24621 --- [nio-5000-exec-6] .s.t.s.TransactionSynchronizationManager : Removed value [org.springframework.orm.jpa.EntityManagerHolder@5ed67928] for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@70286b92] from thread [http-nio-5000-exec-6]
2019-09-12 10:46:41.248 DEBUG 24621 --- [nio-5000-exec-6] o.j.s.OpenEntityManagerInViewInterceptor : Closing JPA EntityManager in OpenEntityManagerInViewInterceptor

阅读 385

收藏
2020-05-30

共1个答案

小编典典

MySQL历史上默认情况下使用MyISAM引擎创建表,该引擎不支持事务。后来添加了支持事务的InnoDB,但是MyISAM在相当长的一段时间内仍然是默认值。

Hibernate的方言遵循相同的默认值,因此MySQL方言的默认值为MyISAM(为了向后兼容)。

您可以通过2种方法来解决此问题:选择特定的方言,或使用特定的属性从MyISAM切换到InnoDB。

要选择一种方言,请使用spring.jpa.database-platform来指定所需的依赖关系。

spring.jpa.database-platform=org.hibernate.dialect.MySQL57InnoDBDialect`

或设置属性使用

spring.jpa.properties.hibernate.dialect.storage_engine=innodb

或两者的组合(因为MySQL57InnoDBDialect现已存在,因此已弃用hibernate.dialect.storage_engine)。

spring.jpa.database-platform=org.hibernate.dialect.MySQL57Dialect
spring.jpa.properties.hibernate.dialect.storage_engine=innodb

另请参见:https :
//in.relation.to/2017/02/20/mysql-dialect-
refactoring/

2020-05-30