【问题标题】:Hibernate session get method returns proxy objectHibernate session get 方法返回代理对象
【发布时间】:2018-01-05 14:35:45
【问题描述】:

我对 Hibernate 会话 get 方法感到困惑。我的理解是get 方法总是返回真实对象而不是代理对象(ref)。

但在我的程序中,即使我使用 get 方法,我也会得到代理对象。

我的场景:

我有两张桌子productcompany

产品 JPA:

@Entity
@Table(name = "PRODUCT")
public class Product {

   @Id
   @Column(name = "prd_id")
   private int id;

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

   @Column(name = "price")
   private int price;

   @ManyToOne(fetch = FetchType.LAZY)
   @JoinColumn(name = "cmp_id")
   private Company company;
}

公司 JPA:

@Entity
@Table(name = "COMPANY")
public class Company {


  @Id
  @Column(name = "cmp_id")
  private int id;

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

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

  @Column(name = "revenue")
  private int revenue;

  @OneToMany(fetch = FetchType.LAZY, mappedBy = "company")
  private List<Product> products;
}

在我的主要方法中,我有以下代码:

    Product product = (Product) session.get(Product.class, 1); // this product has cmp_id 1
    System.out.println("Got product");
    Company company = (Company) session.get(Company.class, 1);
    System.out.println(company instanceof HibernateProxy); // this returns true

我知道由于延迟加载,Hibernate 将公司 1 作为来自Product product = (Product) session.get(Product.class, 1); 的代理对象。 但我期待(Company) session.get(Company.class, 1); 返回正常对象。

从日志中,我看到 hibernate 确实命中了数据库并获得了 Company 对象的完整数据。这使得它更加混乱,如果 hibernate 拥有所有数据,为什么仍然返回代理对象?

我的理解不正确吗?如何确保会话get 返回普通对象而不是代理对象?

【问题讨论】:

  • 您提供的参考文献的一位评论员 (Lluis) 指出:“Javadoc 说:返回具有给定标识符的给定实体类的持久实例,如果没有这样的持久实例,则返回 null。 (如果实例已经与会话关联,则返回该实例。此方法永远不会返回未初始化的实例。)它只会访问数据库一次。具有相同 id 的后续调用将返回缓存的实例。"

标签: java hibernate proxy


【解决方案1】:

Hibernate 不会在每次调用 get 时访问数据库。

请参阅 JavaDocs 获取:If the instance is already associated with the session, return that instance. This method never returns an uninitialized instance.

所以,由于session.get(Product.class) 会话中已经有一个 Company 的实例(虽然是一个代理),所以 Hibernate 只需初始化该代理(因此是您看到的 sql)。

【讨论】:

  • 你能解释一下初始化代理是什么意思吗? Company company = (Company) session.get(Company.class, 1); 语句导致选择查询执行 (select .. from company)。并且在执行选择查询之后,代理对象属性都未初始化。
  • 抱歉,在您的关联中没有看到 FetchType.LAZY。所以你是说在 get(Company.class,1) 之后,即 company.name 是未初始化的(null)?
【解决方案2】:

首先session.get永远不会返回一个代理对象它会从持久空间返回一个完全初始化的对象,如果它存在于那里,否则它会访问数据库从那里获取对象并给它返回 else 返回 null。

正如 java 文档所说:

返回具有给定标识符的给定实体类的持久实例,如果没有这样的持久实例,则返回 null。 (如果实例已经与会话关联,则返回该实例。此方法从不返回未初始化的实例。)

更多信息您可以点击链接“http://docs.jboss.org/hibernate/orm/4.3/javadocs/org/hibernate/Session.html#get(java.lang.Class, java.io.Serializable)”。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-10
    • 2012-11-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多