2

好吧,我的疑问很简单:为了获得最佳性能,建议在我不需要使用的属性中始终使用延迟初始化(这很明显)。所以,想象一下下面的类:

  @Entity
  public class Person{
    @Column
    private String name;
    @ManyToOne(fetch = FetchType.Lazy)
    @JoinColumn(name = "id_type")
    private TypePerson type;
 }

在我的主类中,我调用“类型”属性未初始化的人,如下所示:

 public void init(){
    //in this point "type" attribute is not initialized
    Person person = dao.find("Select * from Person where id = 12");

    //proxys work here to get description of "type" attribute
    System.out.println(person.getType().getDescription());
  }

因此,我从数据库中获取了一个简单的 Person 对象,并在控制台上打印人员的类型。在这一刻,代理 CGLIB 工作并发挥你的作用,一切正常。

但在这里我提出我的问题:

1 - 当我请求“getType()”时,休眠(或其他机制)在幕后进行 SQL 查询?比如:“SELECT * FROM TypePerson where id = 3”。

如果答案是肯定的:这种获取属性值的方法可能非常痛苦,因为我认为 Hibernate 每次都会在数据库中获取这些信息。

如果答案是否定的:如果不是从数据库加载,代理如何知道属性的值?

4

2 回答 2

3

你打电话时

person.getType().getDescription()

如果person正在引用尚未初始化的 Hibernate 代理,那么,是的,它将发出 SQL 查询来检索目标实体的字段值。

这种获取属性值的方法可能非常痛苦,因为我认为 Hibernate 每次都会在数据库中获取这些信息。

每个代理只会执行一次。当它第一次运行时,它将在代理上设置一个标志,表明它已被初始化,因此底层目标实体具有正确的值。如果已加载所有值,则无需返回数据库。

这并不是 Hibernate 创建其代理的确切方式,但它是一个很好的阅读:代理模式

于 2013-11-12T19:08:27.200 回答
1
  1. getDescription()实际上,当在返回的代理上调用该方法时,它会进入数据库person.getType()
  2. 只有当您调用代理上的方法时,它才会进入数据库,即当您真正想要加载代理包装的实体的状态时。它在会话生命周期中只执行一次。对代理方法的下一次调用将不再进入数据库,因为代理已经被上一次方法调用初始化。当然它需要查询数据库。您如何在不查询的情况下从数据库中获取数据?惰性代理的优势恰恰在于它仅在需要时才检索状态。如果您事先知道您将需要 person 类型,那么要么不要使用惰性代理,要么使用在单个查询中加载 person 及其类型的查询。由你决定。
于 2013-11-12T19:10:13.853 回答