【问题标题】:JPA Hibernate Lazy many-to-one fetch proxyJPA Hibernate Lazy 多对一获取代理
【发布时间】:2015-06-05 01:24:18
【问题描述】:

我正在使用 JPA 2.1 和 Hibernate 4.3.7

我尝试调整我的应用程序,以便将关系变得懒惰并只获取我需要的内容

我遇到了多对一关系的问题,当我再次加载实体时变成惰性时,即使我获取实体并且该代理在视图部分中不起作用,休眠也会用代理替换实体( JSF) 的应用程序。 当多对一处于渴望模式时问题消失了,但是即使我不需要它们,休眠也会为每个多对一执行一个选择

@Entity
public class Department {
    @Id
    private Integer id;

    //...
}

1/

@Entity
public class Employee {
    @Id
    private Integer id;

    @ManyToOne(fetch = FetchType.LAZY, optional = true)
    @JoinColumn(name = "id_department", referencedColumnName = "id")
    private Department department;

    //...
}

JPQL 查询:

SELECT e FROM Employee e LEFT JOIN FETCH e.department WHERE e.id=:id

=> 一个选择查询 => 更快,但部门的类型是 Department_$$_jvst3ac_5f (employee.getDepartment().getClass().getCanonicalName()),并且此代理在应用程序的视图部分中不起作用

2/

@Entity
public class Employee {
    @Id
    private Integer id;

    @ManyToOne(fetch = FetchType.EAGER, optional = true)
    @JoinColumn(name = "id_department", referencedColumnName = "id")
    private Department department;

    //...
}

JPQL 查询:

SELECT e FROM Employee e WHERE e.id=:id

=> 两次选择 => 较慢,但部门作为部门加载,并且在应用程序的视图部分一切正常

关系是单向的,部门没有员工的参考

使用 FETCH JOIN 时是否可以让部门没有代理?


在 Luiggi 的响应之后,我将准确地说,数据是通过惰性多对一 + fetch join 获取的。当我做一个employee.getDepartment().toString() 我有Department{ id=11, ...} 但这个部门的类仍然是Department_$$_jvst3ac_5f。由于我不知道的原因,即使获取了数据,JSF/PrimeFaces selectOneMenu 组件也无法在 HibernateProxy 中正常工作

我尝试在 @ManyToOne(fetch = FetchType.LAZY) 之外使用 Hibernate 注释 @LazyToOne(LazyToOneOption.FALSE) 但结果与单独使用 @ManyToOne(fetch = FetchType.EAGER) 相似...

【问题讨论】:

  • 您好,我知道您遇到这个问题已经有一段时间了,但是您找到解决这个问题的优雅方法了吗?

标签: java hibernate jpa lazy-loading many-to-one


【解决方案1】:

问题在于,当您使用延迟加载时,您将获得该类的代理(正如您已经说过的),并且此代理可以从数据库中获取数据只有当 hibernatesession 仍然打开时。似乎在将数据返回到视图时您的会话正在关闭,因此当您尝试在视图中使用延迟加载的字段时,您会遇到异常。

可能的解决方案:

  • 将该字段保持为 fetch eager 并为针对您的实体的每个查询支付开销(可能这不好并且会影响性​​能,但这是一种解决方案)。
  • 在 Hibernate 会话关闭之前将您的字段保持为惰性并使用正确的get 方法,以便代理在会话关闭后检索要使用的相关数据。

【讨论】:

  • 是的,不幸的是,保持字段渴望似乎是唯一的解决方案,为了避免多次选择,我在每个查询中添加了一个 LEFT JOIN FETCH 部门,即使不需要部门(正如我在我使用 get 的帖子不是解决方案)
  • @kwisatz 这是一个解决方案,您不能使用这种方法的事实是另一回事。
  • 那这不是hibernate的bug吗?如果我在自己的事务中执行查询,并且它有一些未初始化的惰性字段,然后在新事务中,我会进行不同的查询,在这种情况下,之前惰性加载的字段的相同实体现在从数据库中急切地获取,该字段不应该使用新的急切获取的实体进行更新吗?
  • @chrismarx 基础 Java:它们是在不同时间创建的不同对象,无法将它们同步为同一个引用。
  • 也许我有一个不同的问题,我遇到了这个问题,hibernate 懒惰地加载特定的用户记录,然后我在另一个事务中为该用户进行查询,但懒惰的记录仍然存在那里,然后这会导致问题
猜你喜欢
  • 2013-10-18
  • 2011-03-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-13
  • 1970-01-01
  • 2019-11-03
  • 2014-12-09
相关资源
最近更新 更多