JSF + Hyperjaxb3 + Hibernate LazyInitializationException 跨请求
我有带有 trinidad 组件的 JSF 应用程序和由 Hyperjaxb3 生成的 JAXB/JPA 实体 bean。在 UI 中,我使用 Trinidad 组合框组件,该组件将 JPA 对象作为值。
该场景是:
- 用户在组合框中进行选择
- 用户单击向服务器发送请求的控件并返回到同一表单
- 表单中的数据已提交,并且组合框中的选择应与用户在步骤 1 中所做的相同。 equals () 方法在组合框项(JPA 对象)上调用,并引发此异常:
org.hibernate.LazyInitializationException:无法延迟初始化角色集合:package.AnObject.items,没有会话或会话已关闭 在 org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:358) 在 org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:350)
at org.hibernate.collection.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:97)
at org.hibernate.collection.PersistentBag.size(PersistentBag.java:225)
at org.jvnet.hyperjaxb3.item.AbstractItemList.size(AbstractItemList.java:51)
at java.util.AbstractList$Itr.hasNext(Unknown Source)
at org.jvnet.jaxb2_commons.lang.builder.JAXBEqualsBuilder.append(JAXBEqualsBuilder.java:57)
at org.jvnet.jaxb2_commons.lang.builder.JAXBEqualsBuilder.append(JAXBEqualsBuilder.java:29)
at package.AnObject.equals(AnObject.java:177)
at org.jvnet.jaxb2_commons.lang.builder.JAXBEqualsBuilder.append(JAXBEqualsBuilder.java:34)
at package.ParentObject.equals(ParentObject.java:532)
at package.ParentObject.equals(ParentObject.java:551)
at java.util.ArrayList.indexOf(Unknown Source)
at org.apache.myfaces.trinidad.component.UIXSelectMany._destructiveCompareOutOfOrderLists(UIXSelectMany.java:179)
at org.apache.myfaces.trinidad.component.UIXSelectMany.compareValues(UIXSelectMany.java:139)
at org.apache.myfaces.trinidad.component.UIXEditableValue.validate(UIXEditableValue.java:180)
at org.apache.myfaces.trinidad.component.UIXEditableValue._executeValidate(UIXEditableValue.java:503)
at org.apache.myfaces.trinidad.component.UIXEditableValue.processValidators(UIXEditableValue.java:270)
at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1058)
at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1058)
我使用 Spring 中的 OpenEntityManagerInViewFilter 来获取延迟加载的对象 - 在一个请求中工作。
在 HyperJAXB 生成的对象级别上,equals()
方法调用 equals(Object object, EqualsBuilder equalsBuilder)
方法,其中 equalsBuilder.append(...)
在该对象的每个属性上调用。当该属性是一个列表时,它由 PersistenBag 代理,这就是我得到 LazyInitializationException 的地方。
equals()
方法 - 由 HyperJaxb 生成:
public boolean equals(Object object) {
if (!(object instanceof ParentObject)) {
return false;
}
if (this == object) {
return true;
}
final EqualsBuilder equalsBuilder = new JAXBEqualsBuilder();
equals(object, equalsBuilder);
return equalsBuilder.isEquals();
}
equals(Object object, EqualsBuilder equalsBuilder)
由 HyperJaxb 生成:
public void equals(Object object, EqualsBuilder equalsBuilder) {
if (!(object instanceof ParentObject)) {
equalsBuilder.appendSuper(false);
return ;
}
if (this == object) {
return ;
}
final ParentObjectthat = ((ParentObject) object);
// PersitentBag, LazyInitializationException is thrown here
equalsBuilder.append(this.getAnObject(), that.getAnObject());
equalsBuilder.append(this.get..., that.get...);
...
}
你们有什么想法如何解决这个问题吗?
我尝试使用 JSF 转换器并让 SelectItem 具有 String 值(不是对象),但如果我记得正确的 equals() 在 String 转换为我的对象之后被调用。
I have JSF application with trinidad components and JAXB/JPA entity beans generated by Hyperjaxb3. In the UI I use Trinidad combo box component that has JPA object as values.
The scenario is:
- User make selection in combo box
- User clicks on a control that sends request to the server and is returned to the same form
- Data from the form was submitted and selection in combo box should be as user did in the step 1. equals() method is called on combo box items (JPA objects) and this exception is thrown:
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: package.AnObject.items, no session or session was closed
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:358)
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:350)
at org.hibernate.collection.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:97)
at org.hibernate.collection.PersistentBag.size(PersistentBag.java:225)
at org.jvnet.hyperjaxb3.item.AbstractItemList.size(AbstractItemList.java:51)
at java.util.AbstractList$Itr.hasNext(Unknown Source)
at org.jvnet.jaxb2_commons.lang.builder.JAXBEqualsBuilder.append(JAXBEqualsBuilder.java:57)
at org.jvnet.jaxb2_commons.lang.builder.JAXBEqualsBuilder.append(JAXBEqualsBuilder.java:29)
at package.AnObject.equals(AnObject.java:177)
at org.jvnet.jaxb2_commons.lang.builder.JAXBEqualsBuilder.append(JAXBEqualsBuilder.java:34)
at package.ParentObject.equals(ParentObject.java:532)
at package.ParentObject.equals(ParentObject.java:551)
at java.util.ArrayList.indexOf(Unknown Source)
at org.apache.myfaces.trinidad.component.UIXSelectMany._destructiveCompareOutOfOrderLists(UIXSelectMany.java:179)
at org.apache.myfaces.trinidad.component.UIXSelectMany.compareValues(UIXSelectMany.java:139)
at org.apache.myfaces.trinidad.component.UIXEditableValue.validate(UIXEditableValue.java:180)
at org.apache.myfaces.trinidad.component.UIXEditableValue._executeValidate(UIXEditableValue.java:503)
at org.apache.myfaces.trinidad.component.UIXEditableValue.processValidators(UIXEditableValue.java:270)
at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1058)
at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1058)
I use OpenEntityManagerInViewFilter from Spring to get lazy loaded objects - that works in one request.
On the level of HyperJAXB generated object equals()
method calls equals(Object object, EqualsBuilder equalsBuilder)
method where equalsBuilder.append(...)
is called on each attribute of that object. When that attribute is a list it is proxied by PersistenBag and that is the point where I get the LazyInitializationException.
equals()
method - generated by HyperJaxb:
public boolean equals(Object object) {
if (!(object instanceof ParentObject)) {
return false;
}
if (this == object) {
return true;
}
final EqualsBuilder equalsBuilder = new JAXBEqualsBuilder();
equals(object, equalsBuilder);
return equalsBuilder.isEquals();
}
equals(Object object, EqualsBuilder equalsBuilder)
generated by HyperJaxb:
public void equals(Object object, EqualsBuilder equalsBuilder) {
if (!(object instanceof ParentObject)) {
equalsBuilder.appendSuper(false);
return ;
}
if (this == object) {
return ;
}
final ParentObjectthat = ((ParentObject) object);
// PersitentBag, LazyInitializationException is thrown here
equalsBuilder.append(this.getAnObject(), that.getAnObject());
equalsBuilder.append(this.get..., that.get...);
...
}
Do you guys have any ideas how fix this problem?
I tried to use JSF converter and have SelectItem with a String value (not object) but if I remember right equals() is called after String is converted to my object.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
之所以会出现这种情况,是因为您的对象未分离 (1),并且您在会话 (3) 之外访问数据 (2)。要更正,您应该以任意组合解决 (1-3)。
就我个人而言,我会首先检查为什么会话不存在。
You get this because your objects are not detached (1) and you access data (2) outside the session (3). To correct, you should address (1-3) in any combination.
Me personally, I'd check first, why is the session not there.