JPA Hibernate Lazy 多对一获取代理
JPA Hibernate Lazy many-to-one fetch proxy
我正在使用 JPA 2.1 和 Hibernate 4.3.7
我尝试调整我的应用程序,因此我将关系变为惰性关系并仅获取我需要的内容
我在多对一关系方面遇到问题,当我再次加载实体时转为惰性时,Hibernate 通过代理替换实体,即使我获取了实体并且该代理在视图中不起作用应用程序的一部分 (JSF)。
当多对一处于急切模式时,问题消失了,但即使我不需要它们,hibernate 也会为每个多对一执行一次 select
@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
=> 一个 select 查询 => 更快但是部门的类型是 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
=> 两个 selects => 较慢但部门作为部门加载并且在应用程序的视图部分一切正常
关系是单向的,部门没有员工的引用
在使用 FETCH JOIN 时是否可以让部门没有代理?
在 Luiggi 的响应之后,我将精确地指出数据是通过惰性多对一 + fetch join 获取的。当我执行 employee.getDepartment().toString() 时,我有 Department{ id=11, ...} 但是这个部门的 class 仍然是 Department_$$_jvst3ac_5f。出于我不知道的原因,即使获取了数据,JSF/PrimeFaces selectOneMenu 组件也无法在 HibernateProxy 中正常工作
我尝试使用 Hibernate 注释 @LazyToOne(LazyToOneOption.FALSE) 除了 @ManyToOne(fetch = FetchType.LAZY) 但结果与 @ManyToOne(fetch = FetchType.EAGER) 一个人...
问题是,当您使用延迟加载时,您将获得 class 的代理(正如您已经说过的),并且此代理可以从数据库中获取数据 只有当 hibernatesession还在营业。将数据返回到视图时,您的会话似乎正在关闭,因此当尝试在视图中使用延迟加载的字段时,您会遇到异常。
可能的解决方案:
- 将该字段保持为急切提取状态,并为针对您的实体的每个查询支付开销(这可能不太好并且会影响性能,但这是一个解决方案)。
- 在关闭 Hibernate 会话之前,将您的字段保持为惰性并使用正确的
get
方法,以便代理在会话关闭后检索要使用的相关数据。
我正在使用 JPA 2.1 和 Hibernate 4.3.7
我尝试调整我的应用程序,因此我将关系变为惰性关系并仅获取我需要的内容
我在多对一关系方面遇到问题,当我再次加载实体时转为惰性时,Hibernate 通过代理替换实体,即使我获取了实体并且该代理在视图中不起作用应用程序的一部分 (JSF)。 当多对一处于急切模式时,问题消失了,但即使我不需要它们,hibernate 也会为每个多对一执行一次 select
@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
=> 一个 select 查询 => 更快但是部门的类型是 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
=> 两个 selects => 较慢但部门作为部门加载并且在应用程序的视图部分一切正常
关系是单向的,部门没有员工的引用
在使用 FETCH JOIN 时是否可以让部门没有代理?
在 Luiggi 的响应之后,我将精确地指出数据是通过惰性多对一 + fetch join 获取的。当我执行 employee.getDepartment().toString() 时,我有 Department{ id=11, ...} 但是这个部门的 class 仍然是 Department_$$_jvst3ac_5f。出于我不知道的原因,即使获取了数据,JSF/PrimeFaces selectOneMenu 组件也无法在 HibernateProxy 中正常工作
我尝试使用 Hibernate 注释 @LazyToOne(LazyToOneOption.FALSE) 除了 @ManyToOne(fetch = FetchType.LAZY) 但结果与 @ManyToOne(fetch = FetchType.EAGER) 一个人...
问题是,当您使用延迟加载时,您将获得 class 的代理(正如您已经说过的),并且此代理可以从数据库中获取数据 只有当 hibernatesession还在营业。将数据返回到视图时,您的会话似乎正在关闭,因此当尝试在视图中使用延迟加载的字段时,您会遇到异常。
可能的解决方案:
- 将该字段保持为急切提取状态,并为针对您的实体的每个查询支付开销(这可能不太好并且会影响性能,但这是一个解决方案)。
- 在关闭 Hibernate 会话之前,将您的字段保持为惰性并使用正确的
get
方法,以便代理在会话关闭后检索要使用的相关数据。