JPA Hibernate Lazy多对一获取代理

kwi*_*atz 5 java hibernate jpa lazy-loading many-to-one

我正在使用JPA 2.1和Hibernate 4.3.7

我试图调整我的应用程序,以便将关系转为懒惰并仅获取我需要的东西

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

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

    //...
}
Run Code Online (Sandbox Code Playgroud)

1 /

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

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

    //...
}
Run Code Online (Sandbox Code Playgroud)

JPQL查询:

SELECT e FROM Employee e LEFT JOIN FETCH e.department WHERE e.id=:id
Run Code Online (Sandbox Code Playgroud)

=>一个选择查询=>更快,但是Department的类型为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;

    //...
}
Run Code Online (Sandbox Code Playgroud)

JPQL查询:

SELECT e FROM Employee e WHERE e.id=:id
Run Code Online (Sandbox Code Playgroud)

=>两个选择=>速度较慢,但​​是Department被加载为Department,并且在应用程序的视图部分中一切正常

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

使用FETCH JOIN时,可以使部门没有代理吗?


在Luiggi做出响应之后,我将精确说明数据是通过惰性多对一+提取联接来提取的。当我执行一个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)类似...

Lui*_*oza 3

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

可能的解决方案:

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