问题描述
我遍历 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
不起作用。注释可以放在方法或类级别,展位工作。
解决方法
从 @Transactional
中删除 uppercaseAllNames
。
这将为您提供单独的读取和每次写入事务。
您需要将 personRepo.save(person)
添加到 FooService.doFoo
以保持更改。
对于 Propagation.REQUIRES_NEW
,第二个更改可能就足够了,但我发现嵌套事务相当混乱,建议避免使用它们。
有同样的问题,上面的接受的答案有效。但我必须将 readOnly=true
添加到外部交易中。