JPA Hibernate Lazy多对一提取代理

时间:2015-03-31 16:01:50

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

我正在使用JPA 2.1和Hibernate 4.3.7

我试图调整我的应用程序,所以我将关系变为懒惰,只获取我需要的内容

我遇到多对一关系的问题,当我再次加载实体时变为懒惰Hibernate通过代理替换实体,即使我获取实体并且此代理在视图部分中不起作用( 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

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

关系是单向的,Department没有提及emplyees

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


在Luiggi的响应之后,我将使用懒惰的多对一+获取连接来获取数据。当我做employee.getDepartment()。toString()时我有Department {id = 11,...}但是这个部门的类仍然是Department _ $$ _ jvst3ac_5f。由于我不知道,即使获取数据,JSF / PrimeFaces selectOneMenu组件也无法正常运行HibernateProxy

我尝试使用Hibernate注释@LazyToOne(LazyToOneOption.FALSE)以及@ManyToOne(fetch = FetchType.LAZY),但结果类似于@ManyToOne(fetch = FetchType.EAGER)...

1 个答案:

答案 0 :(得分:3)

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

可能的解决方案:

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