3

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

我如何告诉 spring 为每个人实体做一个单独的事务,以便 envers 为每个更新的实体写入一个更新修订版,而不是为所有更新的人实体?我还尝试@Transactional(propagation = Propagation.REQUIRES_NEW)将更新服务类放在首位,但并不是每个项目都触发 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
    }
}

解决方案:保存操作触发器允许为每个人实体创建一个修订,但此解决方案仅适用于我们的项目@Transactional(propagation = Propagation.REQUIRES_NEW)。单行@Transactional不行。注释可以放在方法或类级别,展位工作。

4

2 回答 2

3

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

您需要在 中添加 apersonRepo.save(person)FooService.doFoo保留更改。

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

于 2021-05-05T05:12:12.620 回答
1

有同样的问题,上面接受的答案有效。但我不得不添加readOnly=true到外部事务。

于 2021-05-06T09:38:03.653 回答