【问题标题】:Avoid unnecessary SQL select query when getting entity proxy using entityManager.getReference() with hibernate and spring data jpa使用 entityManager.getReference() 和 hibernate 和 spring data jpa 获取实体代理时避免不必要的 SQL 选择查询
【发布时间】:2020-08-23 16:29:46
【问题描述】:

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

我有以下环境和代码

  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 实体是一个只读对象,我需要它作为另一个实体的引用对象。

【问题讨论】:

    标签: hibernate jpa spring-data-jpa entitymanager


    【解决方案1】:

    最后我猜答案很简单。

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

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

    【讨论】:

      【解决方案2】:

      您是否尝试过在 getter 方法上声明 JPA 注释?

      @Entity
      @Table(name = "d20_foo")
      public class Foo {
      
          
          private Long id;
          private String name;
      
          @Id
          @Column(name = "id")
          public Long getId() {
              return id;
          }
      
          public void setId(Long id) {
              this.id = id;
          }
      
          @Column(name = "name")
          public String getName() {
              return name;
          }
      
          public void setName(String name) {
              this.name = name;
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-11-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-01-07
        • 2019-07-20
        相关资源
        最近更新 更多