首页 > 解决方案 > 使用 entityManager.getReference() 和休眠和 spring 数据 jpa 获取实体代理时避免不必要的 SQL 选择查询

问题描述

在尝试使用 Hibernate 作为持久性提供程序通过 Spring 数据存储库获取实体引用时,我正在努力处理不必要的 SQL 选择查询。我的案例涉及多次讨论有关使用entityManager.getReference()的问题,以便在此处此处id获取仅具有初始化值的代理对象。但这并不像描述的那样工作。

我有以下环境和代码

  1. 带有 Hibernate 的 Spring Boot JPA 项目
  2. 一个死的简单实体Foo
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "d20_foo")
public class Foo {

    @Id
    @Column(name = "id")
    private Long id;

    @Column(name = "name")
    private String name;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

在我的服务代码中,我getReference只是像这样调用

@Service
@Transactional
public class MyService {

@PersistenceContext
private EntityManager entityManager;

...
public void getFooLink() {
...
    Foo foo = entityManager.getReference(Foo.class,1L);
...
}
...

}

在调试模式下的休眠日志中,我看到,一旦我点击getReference,就会执行以下选择查询

Hibernate: 
    select
        foo0_.id as id1_0_0_,
        foo0_.name as name2_0_0_ 
    from
        d20_foo foo0_ 
    where
        foo0_.id=?

这是为什么?为什么执行查询而不是只返回代理对象?

我没有点击任何其他字段(例如在返回的对象上调用 getName() )并且按照参考实现中的描述进行了所有操作。

我不需要额外的查询 -Foo实体是一个只读对象,我需要它作为另一个实体的引用对象。

标签: hibernatejpaspring-data-jpaentitymanager

解决方案


最后我想答案很简单。

这是一种调试模式(尤其是在 IntelliJ IDEA中)欺骗了我并显示了这些日志。当我尝试在不调试的情况下监视此代码时(只是将日志写入控制台)-一切都很好。也许当我在调试我的 IDE 时调用一些属性访问器(可能是一个name字段),这会导致 Hibernate 执行选择查询来初始化代理。

所以最后一切都按预期工作


推荐阅读