当我的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;
<<p> 视图/strong> <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上添加子表时(我这样做是为了避免重新加载页面),子表没有更新新行,即使相应的DB事务成功。只有当我通过重新加载页面刷新浏览器中的视图时,新添加的子元素才在表中可见。
然而,请注意,当FetchType
是LAZY
时,当我第一次尝试加载带有父级及其子级的页面时,LazyInitializationException
会发生。这与刷新失败没有直接关系,刷新失败发生在FetchType
为EAGER
时。但我认为我的代码中可能存在一些基本缺陷,修复后,将启用延迟初始化和AJAX视图刷新。
因为你定义了FetchType。惰性抓取childList列;看一下FetchType。LAZY和FetchType。热切的差异从这里。如果你想获得不为空的childList对象,有两个选项:
- FetchType变化。LAZY to FetchType。希望
- 当你的子对象持久化调用getChildren()在@Transaction注释方法。