【发布时间】:2015-07-31 23:51:38
【问题描述】:
当我的JSF 视图请求一个实体的子级列表时,我得到一个LazyInitializationException。我没有直接使用Hibernate,而是JPA。 CHILD DB 表在 PARENT 表上有一个 FK。这是一种非常标准的关系。
以下是相关代码摘录的样子:
家长
@Entity
@Table(name="PARENT")
@NamedQueries({@NamedQuery(name = "Parent.getByID",
query = "SELECT i FROM Parent i WHERE i.parentID = :parentID")})
public class Parent implements Serializable {
@Id
@SequenceGenerator(name="PARENT_SEQ_GEN", sequenceName="DB_SEQ", allocationSize = 1)
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="PARENT_SEQ_GEN")
@Column(name="PARENT_ID")
private long parentID;
/* other stuff */
@OneToMany(cascade = CascadeType.ALL, mappedBy = "parent", fetch = FetchType.LAZY)
private List<Child> childList;
/* other stuff */
public List<Child> getChildren() {
return this.childList;
}
儿童
@Entity
@Table(name="CHILD")
@NamedQueries({@NamedQuery(name = "Child.getByID",
query = "SELECT i FROM Child i WHERE i.childID = :childID")})
public class Child implements Serializable {
@Id
@SequenceGenerator(name="CHILD_SEQ_GEN", sequenceName="DB_SEQ", allocationSize = 1)
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="CHILD_SEQ_GEN")
@Column(name="CHILD_ID")
private long childID;
@JoinColumn(name = "PARENT_ID", referencedColumnName = "PARENT_ID", insertable = true, updatable = false)
@ManyToOne(optional = false)
private Parent parent;
查看
<h:dataTable id="childTbl" value="#{parent.children}"
var="child" width="100%"
styleClass="data" border="1" cellpadding="2"
cellspacing="0">
<h:column>
<f:facet name="header">Child Name</f:facet>
#{child.name}
</h:column>
<h:column>
<f:facet name="header">DOB</f:facet>
#{child.dob}
</h:column>
</h:dataTable>
如果我将 FetchType 更改为 EAGER,我不会收到异常,但我希望数据获取是惰性的,即仅按需获取。为了避免这种异常,我需要进行哪些更改?
可能相关
在视图中,当FetchType 为EAGER 时,它确实成功呈现,我有一个为每个父级添加一个子级的表单,一旦添加了一个子级,我尝试使用f:ajax 刷新子列表自动列出:
<h:commandButton value="Add Child" action="#{parentBean.addChild}">
<f:ajax execute="@form" render="childTbl"/>
</h:commandButton>
但是,即使相应的数据库事务成功,当我在 AJAX 上添加子表时(我这样做是为了避免重新加载页面),由于子表没有用新行更新,刷新失败。仅当我通过重新加载页面在浏览器中刷新视图时,新添加的子项才在表中可见。
但是,请注意LazyInitializationException 出现在我第一次尝试加载包含父母及其子女的页面时,而FetchType 是LAZY。它与刷新失败没有直接关系,当FetchType 是EAGER 时会发生这种情况。但我认为我的代码中可能存在一些根本性缺陷,修复后会启用延迟初始化和 AJAX 视图刷新。
【问题讨论】:
-
交易完成后是否刷新父实体?
-
是的,
<f:ajax execute="@form" render="childTbl"/>应该这样做 -
你可以看到这个答案,同样的问题,但与 jsp 页面 [链接] [1] [1]:stackoverflow.com/questions/19047835/…
-
这是因为您试图在此 EL
#{parent.children}中引用延迟初始化的集合。我假设 EL 指的是private List<Child> childList由getChildren()在Parent实体中返回。这与 JSF 没有任何关系。根据功能要求或项目的结构/流程,使用单独的查询根据其父行检索子级列表。
标签: hibernate jsf jpa lazy-loading