【发布时间】:2022-01-25 02:36:51
【问题描述】:
我有以下示例代码:
@Transactional
public void someMethod() {
MyEntity myEntity = myRepo.findById(1).orElse(null);
if (myEntity != null) {
myEntity.setValue("something");
myRepo.save(myEntity);
}
}
而myRepo 是一个实例:
public interface MyRepo extends CrudRepository<MyEntity, Integer> {}
所以我可以看到第一个 SELECT 来自 myRepo.findById(1),这是有道理的。但是当代码运行到myRepo.save(myEntity) 时,Hibernate 以某种方式认为从findById() 返回的myEntity 不是托管的,因此它再次执行另一个 SELECT 以创建托管实体,然后使用 myEntity 替换其值,然后执行更新。
您能否解释一下为什么需要另一个 SELECT 以及如何避免它?此外,方法上方的 @Transactional 注释无论有没有它都不会改变这种行为。
【问题讨论】:
-
你从哪里打电话给
someMethod? (另外,你正在积极反对Optional:myRepo.findById(1).ifPresent...) -
@chrylis-cautiouslyoptimistic- 它在服务中调用,由 Web 请求调用。
-
所以是自调用?那么建议不起作用。
-
@chrylis-cautiouslyoptimistic- 你的简短评论中有相当多的信息,你的意思是: 1. 如果不是自调用,
@Transactional将生效 2.@Transactional正是需要阻止 Hibernate 在 UPDATE 之前执行另一个 SELECT 并且从findById()返回的myEntity将被管理?
标签: java spring spring-boot hibernate jpa