gpt4 book ai didi

jsf - com.sun.faces.renderkit.html_basic.MenuRenderer.convertSelectManyValuesForModel 处的 org.hibernate.LazyInitializationException

转载 作者:行者123 更新时间:2023-12-02 01:52:56 28 4
gpt4 key购买 nike

尽管FetchType.EAGERJOIN FETCH ,我得到一个LazyInitalizationException将一些对象添加到 @ManyToMany 时通过 JSF 收集 UISelectMany组件,例如我的例子中的 <p:selectManyMenu> .

@Entity IdentUser ,与 FetchType.EAGER :

@Column(name = "EMPLOYERS")
@ManyToMany(fetch = FetchType.EAGER, cascade= CascadeType.ALL)
@JoinTable(name = "USER_COMPANY", joinColumns = { @JoinColumn(name = "USER_ID") }, inverseJoinColumns = { @JoinColumn(name = "COMPANY_ID") })
private Set<Company> employers = new HashSet<Company>();

@Entity Company ,与 FetchType.EAGER :

@ManyToMany(mappedBy="employers", fetch=FetchType.EAGER)
private List<IdentUser> employee;

JPQL,带有 JOIN FETCH :

public List<IdentUser> getAllUsers() {
return this.em.createQuery("from IdentUser u LEFT JOIN FETCH u.employers WHERE u.enabled = 1 AND u.accountNonLocked=0 ").getResultList();
}

JSF UISelectMany提交时导致异常的组件:

<p:selectManyMenu value="#{bean.user.employers}" converter="#{entityConverter}">
<f:selectItems value="#{bean.companies}" var="company" itemValue="#{company}" itemLabel="#{company.name}"/>
</p:selectManyMenu>

堆栈跟踪的相关部分:

org.hibernate.LazyInitializationException: failed to lazily initialize a collection, could not initialize proxy - no Session
at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:566)
at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:186)
at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:545)
at org.hibernate.collection.internal.PersistentSet.add(PersistentSet.java:206)
at com.sun.faces.renderkit.html_basic.MenuRenderer.convertSelectManyValuesForModel(MenuRenderer.java:382)
at com.sun.faces.renderkit.html_basic.MenuRenderer.convertSelectManyValue(MenuRenderer.java:129)
at com.sun.faces.renderkit.html_basic.MenuRenderer.getConvertedValue(MenuRenderer.java:315)
at org.primefaces.component.selectmanymenu.SelectManyMenuRenderer.getConvertedValue(SelectManyMenuRenderer.java:37)
...

这是怎么造成的,如何解决?

最佳答案

提交时,JSF UISelectMany组件需要创建一个全新集合实例,并预先填充提交和转换的值。它不会清除并重用模型中的现有集合,因为这可能会反射(reflect)在对同一集合的其他引用中,或者可能会失败并显示 UnsupportedOperationException因为集合是不可修改的,比如Arrays#asList()获取的集合或Collections#unmodifiableList()

MenuRenderer UISelectMany 背后的渲染器默认情况下,负责这一切的(和 UISelectOne )组件将基于集合的 getClass().newInstance() 创建集合的全新实例。 。这又会失败并显示 LazyInitializationException如果getClass()返回 Hibernate 的 PersistentCollection 的实现Hibernate 在内部使用它来填充实体的集合属性。 add()即需要通过当前 session 初始化底层代理,但没有,因为该作业不是在事务服务方法中执行。

要覆盖 MenuRenderer 的此默认行为,您需要通过collectionType显式指定所需集合类型的FQN UISelectMany 的属性成分。对于List属性,您想要指定 java.util.ArrayList对于 Set属性,您想要指定 java.util.LinkedHashSet (或 java.util.HashSet 如果排序不重要):

<p:selectManyMenu ... collectionType="java.util.LinkedHashSet">

这同样适用于所有其他 UISelectMany以及直接绑定(bind)到 Hibernate 管理的 JPA 实体的组件。例如:

<p:selectManyCheckbox ... collectionType="java.util.LinkedHashSet">
<h:selectManyCheckbox ... collectionType="java.util.LinkedHashSet">
<h:selectManyListbox ... collectionType="java.util.LinkedHashSet">
<h:selectManyMenu ... collectionType="java.util.LinkedHashSet">

另请参阅VDL documentation of among others <h:selectManyMenu> 。不幸的是,VDL documentation of <p:selectManyMenu> 中没有指定这一点。 ,但由于它们使用相同的渲染器进行转换,因此它必须有效。如果 IDE 因未知的问题而抖动 collectionType属性并烦人地强调它,即使它在您忽略并运行它时起作用,然后使用 <f:attribute>相反。

<p:selectManyMenu ... >
<f:attribute name="collectionType" value="java.util.LinkedHashSet" />
...
</p:selectManyMenu>

关于jsf - com.sun.faces.renderkit.html_basic.MenuRenderer.convertSelectManyValuesForModel 处的 org.hibernate.LazyInitializationException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25245426/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com