【问题标题】:Hibernate does another select before saveHibernate 在保存之前进行另一个选择
【发布时间】: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? (另外,你正在积极反对OptionalmyRepo.findById(1).ifPresent...
  • @chrylis-cautiouslyoptimistic- 它在服务中调用,由 Web 请求调用。
  • 所以是自调用?那么建议不起作用。
  • @chrylis-cautiouslyoptimistic- 你的简短评论中有相当多的信息,你的意思是: 1. 如果不是自调用,@Transactional 将生效 2. @Transactional 正是需要阻止 Hibernate 在 UPDATE 之前执行另一个 SELECT 并且从 findById() 返回的 myEntity 将被管理?

标签: java spring spring-boot hibernate jpa


【解决方案1】:

它来自 @Transactional 在 Spring 中的不太明确的行为。 @Transactional 意味着两件事:

  1. 打开的持久上下文(休眠会话)
  2. 交易本身。

您有第二个选择,因为在您的情况下 @Transactional 根本不起作用。 Hibernate 为每个调用打开一个新的持久上下文

  1. myRepo.findById(1)
  2. myRepo.save(myEntity)

如果您想进行自调用,则需要将对您的服务的引用传递给您调用事务方法的方法。

class SomeServiceImpl implements SomeService {

    public void doWork(SomeService self) {
        self.someMethod();
    }

    @Transactional
    public void someMethod() {
        MyEntity myEntity = myRepo.findById(1).orElse(null);
        if (myEntity != null) {
            myEntity.setValue("something");
            myRepo.save(myEntity);
        }
    }

}

例子

SomeService service;
service.doWork(service);

另一种方法是将self 自动写入服务字段。但这不是很好,因为您必须通过归档注入来使用自动软件。使用构造函数来实现自动化是不可能的。所以很难对服务进行单元测试。

【讨论】:

  • 谢谢,所以不是事务方法也不是 Hibernate 有任何问题,而是方法被调用的方式。我已经通过将方法从服务移动到存储库来解决它(作为默认方法)。
  • @user1589188 当您将方法移动到存储库时。您开始通过代理调用该方法,@Transactional 开始工作。我不确定存储库是否适合它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-18
  • 2021-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多