Spring Data与JPA在错误发生时未回滚事务。

6
我们已经为JPA配置了Spring Data。服务事务方法不会因错误(例如DB ConstraintViolationException)而回滚。
我找到的最接近的是这个(Transaction not rolling back) Spring-data, JTA, JPA, Wildfly10,但我们没有任何XML配置,所有的配置都是基于Java的。
本质上,服务方法看起来像这样:没有捕获任何错误,抛出所有异常。
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class, readOnly = false)
public void insertEvent() throws Exception {
     // Part 1
     EventsT event = new EventsT(); 
     // populate it..
     eventsDAO.save(event);

     // Part 2 - ERROR HAPPENS HERE (Constraint Violation Exception)
     AnswersT answer = new AnswersT();
     // populate it..
     answersDAO.save(answer);   
}

第二部分失败了。但是在错误和返回之后,我发现事件(第一部分)仍然存在于数据库中。

我们还尝试了各种@ Transactional的组合,但都没有成功:

@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class, readOnly = false)
@Transactional(readOnly = false)
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = ConstraintViolationException.class, readOnly = false)

Spring Data CRUD DAO 接口:

@Repository
public interface EventsDAO extends JpaRepository<EventsT, Integer> {

}

@Repository
public interface AnswersDAO extends JpaRepository<AnswersT, Integer> {

}

JpaConfig:
@Configuration
@EnableJpaRepositories(basePackages = "com.myapp.dao")
@PropertySource({ "file:${conf.dir}/myapp/db-connection.properties" })
public class JpaConfig {

    @Value("${jdbc.datasource}")
    private String dataSourceName;

    @Bean
    public Map<String, Object> jpaProperties() {
        Map<String, Object> props = new HashMap<String, Object>();
        props.put("hibernate.dialect", PostgreSQL95Dialect.class.getName());
        //props.put("hibernate.cache.provider_class", HashtableCacheProvider.class.getName());
        return props;
    }

    @Bean
    public JpaVendorAdapter jpaVendorAdapter() {
        HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter();
        hibernateJpaVendorAdapter.setShowSql(true);
        hibernateJpaVendorAdapter.setGenerateDdl(true);
        hibernateJpaVendorAdapter.setDatabase(Database.POSTGRESQL);
        return hibernateJpaVendorAdapter;
    }

    @Bean
    public PlatformTransactionManager transactionManager() throws NamingException {
        return new JpaTransactionManager( entityManagerFactory().getObject() );
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() throws NamingException {
        LocalContainerEntityManagerFactoryBean lef = new LocalContainerEntityManagerFactoryBean();
        lef.setDataSource(dataSource());
        lef.setJpaPropertyMap(this.jpaProperties());
        lef.setJpaVendorAdapter(this.jpaVendorAdapter());
        lef.setPackagesToScan("com.myapp.domain", "com.myapp.dao");
        return lef;
    }

    @Bean
    public DataSource dataSource() throws NamingException {
        return (DataSource) new JndiTemplate().lookup(dataSourceName);
    }   

}

Spring Data和JPA是否存在任何事务回滚问题?

只是为了澄清,您使用的是 org.springframework.transaction.annotation.Transactional 还是 javax.transaction.Transactional?而且 insertEvent() 是在流程中第一个被注释为 Transactional 的方法吗? - lzagkaretos
事务性注解是 org.springframework.transaction.annotation.Transactional。是的,insertEvent 方法如上所示被标记为 @Transactional。 - gene b.
什么是DB?MySQL情况下:没有使用engine=InnoDB引擎无法回滚。 - Henrique Fernandes Cipriano
PostgreSQL。事实上,即使我尝试进行删除操作,Spring Data也会抱怨没有事务:javax.persistence.TransactionRequiredException:执行更新/删除查询。因此,即使我已经注释了它,事务也无法找到! - gene b.
2个回答

4

信不信由你,我们已经修复了它。解决方案包括两个部分:

1)像ledniov所描述的那样,在JpaConfig中添加@EnableTransactionManagement,但仅此还不够;

2)同样在JpaConfig的entityManagerFactory()中,将Service类包添加到以下setPackagesToScan。之前只有领域对象包,没有服务对象包。我们添加了第二个包"myapp.service"

@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() throws NamingException {
    LocalContainerEntityManagerFactoryBean lef = new LocalContainerEntityManagerFactoryBean();
    lef.setDataSource(dataSource());
    lef.setJpaPropertyMap(this.jpaProperties());
    lef.setJpaVendorAdapter(this.jpaVendorAdapter());
    lef.setPackagesToScan("myapp.domain", "myapp.service"); //NOTE: Service was missing
    return lef;
}

这可能有点晚了,但只是分享一下。 我也遇到了同样的问题,而我失败的唯一原因是我必须添加 rollBackFor = Exception.class 用于@Transactional我将包路径添加到setPackagesToScan中并将其删除,但得到了相同的结果。 - Ran

2
要启用Spring的注解驱动事务管理功能,您需要在JpaConfig类中添加@EnableTransactionManagement注解。请注意保留HTML标记。

好的建议,我已经添加了,但是事务仍然没有回滚。我发现在同一个事务服务方法中,在 Part #2 中出现错误后,Part #1 仍然被保留。 - gene b.
我们修复了它 - 我回答了这个问题。感谢您的帮助。 - gene b.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接