循环遍历 jpa streamresult 的项目并调用更新服务。 Envers 对所有项目创建修订,而不是为每个项目创建修订

Looping over items of a jpa streamresult and call an update service. Envers create an revision over all items instead for every single item

我遍历 jpa streamresult 的个人实体,并为每个人调用一个更新服务 bean 来更新个人实体的名称。我明白,envers 是在交易结束时执行的。好的,这工作正常,所有实体都已更新并有一个 AUD table 条目,但所有实体都只有一个修订版。

我如何告诉 spring 为每个人实体执行单个事务,以便 envers 为每个更新的实体写入单个更新修订而不是为所有更新的个人实体?我还尝试将 @Transactional(propagation = Propagation.REQUIRES_NEW) 置于更新服务 class 的顶部,但并不是每个项目都会触发 envers。似乎所有更新都在一个事务中执行,但我需要为更新服务 bean 的每次调用一个事务。

流媒体服务:

@Service
class StreamService {

    @Autowired
    PersonRepository repo;

    @Autowired
    FooService fooService;

    @Transactional
    public void uppercaseAllNames() {
        Stream<Person> stream = repo.findAllPersons();
    
         // change name for each person
        stream.forEach(fooService::doFoo);
    }

}

简化更新服务:

@Service
@Transactional(propagation = Propagation.REQUIRES_NEW) // <=== create new transaction
class FooService {

    @Autowired
    PersonRepository repo;

    doFoo(Person person) {
        String name = person.getName();
        person.setName(name.toUpperCase());
        repo.save(person); // <=== save trigger envers
    }
}

解决方法: 保存操作触发 envers 以创建每个人实体的修订,但此解决方案仅在我们的项目中适用于 @Transactional(propagation = Propagation.REQUIRES_NEW)。单个 @Transactional 不起作用。注释可以放在方法或 class 级别,booth places work.

uppercaseAllNames 中删除 @Transactional。 这将为您提供单独的读取和写入事务。

您需要将 personRepo.save(person) 添加到 FooService.doFoo 以保留更改。

可能 Propagation.REQUIRES_NEW 第二个更改就足够了,但我发现嵌套事务相当混乱,建议避免使用它们。

有同样的问题并且上面的已接受答案有效。但是我必须将 readOnly=true 添加到外部事务中。