当前位置: 首页 > 知识库问答 >
问题:

错误时JPA不回滚事务的Spring数据

周威
2023-03-14

我们为JPA配置了Spring数据。服务事务方法不会因错误而回滚(例如,DB ConstraintViolationException)。

我能找到的最接近的是这个(事务不回滚)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(propagation = Propagation.REQUIRED, rollbackFor = Exception.class, readOnly = false)
@Transactional(readOnly = false)
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = ConstraintViolationException.class, readOnly = false)
@Repository
public interface EventsDAO extends JpaRepository<EventsT, Integer> {

}

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

}
@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);
    }   

}

共有1个答案

丌官飞章
2023-03-14

信不信由你我们修好了。解决方案有两个部分:

1)如ledniov所述,将@enableTransactionManagement添加到JpaConfig,但仅此还不够;

2)同样在EntityManagerFactory()的JpaConfig中,将服务类包添加到下面的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;
}
 类似资料:
  • 我试图在一个事务中插入两个记录到我的数据库中。第二次插入失败,但是在回滚中第一次插入没有被删除: (我还尝试将save方法替换为:jpaContext.getEntityManagerByManagedType(WebMessage.class)。坚持(wm);因此,我不使用crud保存,但问题仍然存在) 我启用了事务日志以查看发生了什么,我发现: 在调用test()之前,会创建一个新事务,因为@

  • 我们有一个Spring事务回滚问题,其中回滚似乎不起作用 在用注释的服务层方法中,我调用三个不同的类来插入3条记录 中间插入从第四个表执行get以填充描述字段,但此get失败。我希望第一次插入会回滚,但它似乎没有发生 几点: 获取方法抛出运行时异常 我们使用和中定义的。Bean是在中创建的,它被导入到 在层 中没有 注释 我们已经使用了

  • 你能告诉我如何只对某些代码块运行事务吗?我有@Transactional的服务函数,并从它们调用存储库函数,在那里执行查询。但当查询失败时,由于事务必须结束,服务功能也随之失效。那么,当存储库函数失败时,如何返回null值呢?我需要在失败时捕获空值,并继续一些逻辑。我的代码: 我尝试了@davidxxx的答案,得到了这个错误:

  • 我试图编写一个spring-cloud-stream函数(spring-starter-parent 2.5.3,java 11,spring-cloud-version 2020.0.3),该函数同时具有Kafka和Postgres事务。每当使用的消息以字符串“fail”开始时,该函数将引发一个模拟错误,我希望这将导致数据库事务回滚,然后导致kafka事务回滚。(我知道Kafka交易不是XA,这

  • 这很好,但并不总是在代码中抛出运行时异常。因此,我挖掘并发现如下所示的rollbackFor; 现在,我必须更改所有代码,以使用RollBackfor更改@Transactional。但是还有其他方法可以将所有@transaction advice属性更改为rollbackFor=exception.class吗?

  • 我有一个由Spring框架维护的对象,我使用注释将它注入到我想要的任何DAO类中,如下所示。 我使用那些DAO类在数据库中保存如下内容。 现在,这里的两个DAO都使用了通过注入的相同的。现在,如果在之后发生异常,那么我甚至希望回滚保存的实体。但是,如何从中获取? 如果所有DAO都持有相同的对象,那么我可以直接调用类的方法吗?返回新事务或当前与关联的任何事务吗?