Spring JPA:从异步方法处理时数据未保存到数据库

问题描述 投票:0回答:2

我有一个使用 Spring JPA 的应用程序,并使用 @Async spring 注释执行一些后台进程。该过程需要将参数保存在数据库中,或者如果已经存在,则更新数据库。

这不起作用,因为在

@Async
方法完成后,我的数据实体没有保留在数据库中。但是当我从方法中删除
@Async
注释时,一切工作正常。我的数据已保存或更新在数据库中。

有人知道可能出了什么问题或者我可能错过了什么吗?

谢谢。

** 更新[代码示例]

异步服务

@Service
@EnableAsync
class AsyncService() {
    @Async
    public void process(firstEntity, secondEntity) {
        firstEntity = prepareParams(firstEntity);
        secondEntity = prepareParams(secondEntity);
        save(firstEntity, secondEntity);
    }
}

实体关系服务

@Transactional
@Service
class EntityRelationService() {

    private SecondEntityRepo secondEntityRepo;

    @Autowired
    public EntityRelationService(SecondEntityRepo secondEntityRepo) {
        this.secondEntityRepo = secondEntityRepo;
    }

    @Transactional
    public void save(p1, p2) {
        p2.setRelation(p1);

        this.secondEntityRepo(p2);
    }
}

Bean 配置

@Bean
@Primary
@ConfigurationProperties(prefix = "app.database")
public DataSource dataSource() {
    DriverManagerDataSource dataSource = new DriverManagerDataSource();
    dataSource.setDriverClassName(driver);
    dataSource.setUrl(url);
    dataSource.setUsername(username);
    dataSource.setPassword(password);
    return dataSource;
}

@Bean
@Primary
public LocalSessionFactoryBean sessionFactory() {
    LocalSessionFactoryBean sf = new LocalSessionFactoryBean();
    sf.setDataSource(dataSource());
    sf.setPackagesToScan("com.app");
    Properties props = new Properties();
    props.put("hibernate.use_sql_comments", false);
    props.put("hibernate.show_sql", true);
    sf.setHibernateProperties(props);
    return sf;
}

@Bean
public HibernateTransactionManager transactionManager() {
    HibernateTransactionManager transactionManager =
            new HibernateTransactionManager();
    transactionManager.setSessionFactory(sessionFactory().getObject());
    return transactionManager;
}
spring hibernate spring-boot spring-data spring-data-jpa
2个回答
2
投票

我猜测 @Async 方法与 @Transactional 位于同一类中。

注意:@Async 将创建一个不是事务性的新线程(因此不会写入数据库)。使用Spring代理的东西,你的异步方法需要调用另一个类上的方法才能恢复@Transactional。

换句话说,使用 @Async 方法创建一个新的空类,该方法仅调用原始类(具有 @Transactional)中的 main 方法。

一个简单的例子如下所示:

真实服务的代理:

@Service
@EnableAsync
class AsyncService() {
    private SyncService syncService;

    @Async
    public void process(String param) {
        syncService.process(param);
    }
}

真正的服务:

@Service
@Transactional
class SyncService() {
    public void process(String param) {
        // ... Do whatever you want
    }
}

0
投票

我也有类似的问题: 每当方法 (A) 引发异常时,所有更改都会回滚。此外,从方法 (A) 调用的其他方法内发生的所有更改都会回滚。

我的解决方案是将以下注释放在一个方法上,无论其他地方发生什么,我都确保始终保存对象:

import org.springframework.transaction.annotation.Transactional;


@Transactional(propagation = Propagation.REQUIRES_NEW)
public void doStuff() {
...
}
© www.soinside.com 2019 - 2024. All rights reserved.