更新:该表已设置为MyISAM而不是InnoDB,从而解决了该问题。
所以我有这个方法:
@Transactional()
@Override
public List<Order> findAll() {
Order order = new Order();
Order order1 = new Order();
Order order2 = new Order();
orderRepository.save(order);
orderRepository.save(order1);
orderRepository.save(order2);
return orders;
}
当其中一个引发异常时,其他不回滚。我试图设置一些错误的数据类型以获取DataException,但是后来我意识到这可能是一个检查异常?所以我这样做了:
order2.setDishesReady(5);
if(order2.getDishesReady() == 5){
throw new RuntimeException();
}
仍然没有回滚。我也尝试过
@Transactional(propagation=Propagation.REQUIRED)
@Transactional(rollbackFor = Exception.class)
还有没有办法伪造这样的回滚?通过在方法中引发异常,如果没有,如何测试回滚?这是我的配置:
@Configuration
@EnableWebMvc
@EnableTransactionManagement
public class AppConfig {
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean em
= new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource());
em.setPackagesToScan("com.project.models");
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
em.setJpaProperties(additionalProperties());
return em;
}
@Bean
public DataSource dataSource(){
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/project");
dataSource.setUsername( "root" );
dataSource.setPassword( "1234" );
return dataSource;
}
@Bean
public PlatformTransactionManager transactionManager(
EntityManagerFactory emf){
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(emf);
return transactionManager;
}
@Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation(){
return new PersistenceExceptionTranslationPostProcessor();
}
Properties additionalProperties() {
Properties properties = new Properties();
properties.setProperty(
"hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");
return properties;
}
使用日志中的某些内容进行更新:
Creating new EntityManager for shared EntityManager invocation
""2019-02-10 09:30:05 - Closing JPA EntityManager
""2019-02-10 09:30:05 - Creating new EntityManager for shared EntityManager invocation
""2019-02-10 09:30:05 - Closing JPA EntityManager
""2019-02-10 09:30:05 - Creating new EntityManager for shared EntityManager invocation
""2019-02-10 09:30:05 - Closing JPA EntityManager
""2019-02-10 09:30:05 - Creating new EntityManager for shared EntityManager invocation
""2019-02-10 09:30:05 - Closing JPA EntityManager
""2019-02-10 09:30:05 - Creating new EntityManager for shared EntityManager invocation
""2019-02-10 09:30:05 - Closing JPA EntityManager
""2019-02-10 09:30:05 - Creating new EntityManager for shared EntityManager invocation
""2019-02-10 09:30:05 - Closing JPA EntityManager
""2019-02-10 09:30:05 - Creating new EntityManager for shared EntityManager invocation
""2019-02-10 09:30:05 - Closing JPA EntityManager
""2019-02-10 09:30:05 - Creating new EntityManager for shared EntityManager invocation
""2019-02-10 09:30:05 - Closing JPA EntityManager
""2019-02-10 09:30:05 - Creating new EntityManager for shared EntityManager invocation
""2019-02-10 09:30:05 - Closing JPA EntityManager
""2019-02-10 09:30:05 - Creating new EntityManager for shared EntityManager invocation
""2019-02-10 09:30:05 - Closing JPA EntityManager
""2019-02-10 09:30:06 - spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
""2019-02-10 09:30:06 - Creating filter chain: any request, [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@1d1cfe4, org.springframework.security.web.context.SecurityContextPersistenceFilter@10745a02, org.springframework.security.web.header.HeaderWriterFilter@3d798e76, org.springframework.web.filter.CorsFilter@ba562e0, org.springframework.security.web.authentication.logout.LogoutFilter@13c90c06, com.vision.project.security.JwtAuthenticationTokenFilter@7c447c76, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@72715e61, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@5611bba, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@5a51336a, org.springframework.security.web.session.SessionManagementFilter@386e9fd8, org.springframework.security.web.access.ExceptionTranslationFilter@5403431a, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@58b8f9e3]
""2019-02-10 09:30:07 - Initializing ExecutorService 'taskScheduler'
""2019-02-10 09:30:07 - Cannot find template location: classpath:/templates/ (please add some templates or check your Thymeleaf configuration)
""2019-02-10 09:30:07 - Tomcat started on port(s): 8080 (http) with context path ''
""2019-02-10 09:30:07 - Started ProjectApplication in 13.85 seconds (JVM running for 15.214)
""2019-02-10 09:31:09 - Initializing Spring DispatcherServlet 'dispatcherServlet'
""2019-02-10 09:31:09 - Initializing Servlet 'dispatcherServlet'
""2019-02-10 09:31:09 - Completed initialization in 16 ms
""2019-02-10 09:31:09 - Opening JPA EntityManager in OpenEntityManagerInViewInterceptor
""2019-02-10 09:31:09 - Found thread-bound EntityManager [SessionImpl(1272634933<open>)] for JPA transaction
""2019-02-10 09:31:09 - Creating new transaction with name [com.vision.project.services.OrderServiceImpl.findAll]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,-java.lang.RuntimeException,-java.lang.Exception
""2019-02-10 09:31:09 - Exposing JPA transaction as JDBC [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@7234e97]
""2019-02-10 09:31:09 - Found thread-bound EntityManager [SessionImpl(1272634933<open>)] for JPA transaction
""2019-02-10 09:31:09 - Participating in existing transaction
""2019-02-10 09:31:09 - Found thread-bound EntityManager [SessionImpl(1272634933<open>)] for JPA transaction
""2019-02-10 09:31:09 - Participating in existing transaction
""2019-02-10 09:31:09 - Initiating transaction rollback
""2019-02-10 09:31:09 - Rolling back JPA transaction on EntityManager [SessionImpl(1272634933<open>)]
""2019-02-10 09:31:09 - Not closing pre-bound JPA EntityManager after transaction
""2019-02-10 09:31:09 - Closing JPA EntityManager in OpenEntityManagerInViewInterceptor
""2019-02-10 09:31:09 - Closing JPA EntityManager
4.4级,Java 8, 依赖项:
compile('org.springframework.boot:spring-boot-starter-thymeleaf')
compile('org.springframework.boot:spring-boot-starter-web')
compile("org.springframework.boot:spring-boot-starter-security")
testCompile('org.springframework.boot:spring-boot-starter-test')
compile "org.springframework.boot:spring-boot-configuration-processor"
compile group: 'org.springframework.boot', name: 'spring-boot-starter-data-jpa', version: '2.1.2.RELEASE'
compile group: 'org.springframework', name: 'spring-jdbc', version: '5.0.8.RELEASE'
compile group: 'org.springframework.boot', name: 'spring-boot-starter-security', version: '1.2.5.RELEASE'
compile group: 'org.springframework.security', name: 'spring-security-jwt', version: '1.0.2.RELEASE'
compile group: 'org.hibernate', name: 'hibernate-core', version: '5.4.1.Final'
compile group: 'org.hibernate', name: 'hibernate-gradle-plugin', version: '5.3.5.Final'
compile group: 'io.jsonwebtoken', name: 'jjwt', version: '0.6.0'
compile group: 'mysql', name: 'mysql-connector-java', version: '5.1.6'
compile group: 'com.mchange', name: 'c3p0', version: '0.9.5.2'
答案 0 :(得分:0)
我正在回答要跳过更新的人们的问题。所以一段时间后,我意识到这样的事情:
orderRepository.save(order1);
orderRepository.save(order2);
Order order = orderRepository.save(order3);
order.setDishesReady = 5;
orderRepository.delete(order3);
if(order3.getDishesReady() == 5){
throw new RuntimeException();
}
仅对删除操作进行回滚,对保存操作不进行回滚,经过更多研究,我发现我的表设置为MyISAM而不是InnoDB。 来自What's the difference between MyISAM and InnoDB?的更多有关该主题的信息:
如果您需要数据库来强制执行外键约束,或者您需要数据库来支持事务(即,由两个或多个DML操作进行的更改作为单个工作单元处理,则所有更改都已应用,或者所有更改已恢复),则您将选择InnoDB引擎,因为MyISAM引擎缺少这些功能。
答案 1 :(得分:-1)
@Transactional仅回退未检查异常的事务。对于检查的异常及其子类,它将提交数据。因此,尽管在这里引发了一个异常,但由于它是一个已检查的异常,因此Spring会忽略该异常并将数据提交到数据库中,从而导致系统不一致。
@Transactional(rollbackFor = Exception.class)
如果抛出Exception或其子类,请始终将其与@Transactional批注一起使用,以告诉Spring如果发生检查的异常,则回滚事务。