使用Spring的异步执行时,实体无法持久存储在数据库中

时间:2019-05-03 13:23:30

标签: java spring transactions spring-data

我需要运行一个异步作业,该作业将数据(从文件读取)导入到MySQL DB。我正在使用Spring Data的CrudRepository。问题是,尽管调用了save方法,但是没有数据持久保存到数据库中。

老实说,我不知道如何开始解决这个问题。我在日志中没有看到任何错误或警告,并且在Google上搜索时,我仅发现以下建议:

Spring JPA: Data not saved to Database when processing from an Async method

但是,我已经应用了它,但是我的代码仍然无法正常工作。同步运行代码(通过删除@Async批注),一切都会按预期进行。

我的代码段:

AsyncImportService.java

@Service
public class AsyncImportService {
    @Autowired
    private ImportService importService;

    @Async
    public void import() {
        importService.import();
    }
}

ImportService.java

@Service
public class ImportService {
    @Autowired
    private AddressCrudRepository addressRepository;

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void import() {
        List<Adres> adresses = new ArrayList<>();

        // Open file and create buffered reader using try-with-resources
        try (BufferedReader reader = ...) {
            while((line = reader.readLine()) != null) {
                // mapAddress converts a line of text to an Address object
                addresses.add(mapAddress(line));
            }

            addressRepository.save(adresses);
        } catch (IOException e) {
            // Handle exception
        }
    }
}

AdresCrudRepository.java

public interface AddressCrudRepository extends CrudRepository<Address, Long> {
}

我希望将地址保存到数据库中,但是在运行作业(并且没有收到任何错误或警告)之后,数据库仍为空。

我已经盯着看了好几个小时了,所有想法都欢迎!

1 个答案:

答案 0 :(得分:0)

在调用@Async时可能已经有一个事务在运行,因此异步方法选择了相同的事务上下文。

另一面是,异步方法完成之前,事务可能已经由父代码提交了。

通常,建议使用新的/嵌套事务调用异步方法:

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void import() {

由于它不会依赖于父事务。

更新

您还要保存一个实体列表。尝试使用:

addressRepository.saveAll(adresses);