16

FetchType.EAGERとにもかかわらず、JOIN FETCH私の場合は.LazyInitalizationException@ManyToManyUISelectMany<p:selectManyMenu>

@Entity IdentUserFetchType.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 CompanyFetchType.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();
}

UISelectManyサブミット中に例外を引き起こした JSFコンポーネント:

<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)
    ...

これはどのように発生し、どうすれば解決できますか?

4

2 に答える 2

32

送信中、JSFUISelectManyコンポーネントは、送信され変換された値が事前に入力されたコレクションの新しいインスタンスを作成する必要があります。モデル内の既存のコレクションをクリアして再利用することはありません。これは、同じコレクションへの他の参照に反映されるか、 または によって取得されたものなど、コレクションが変更できないために で失敗する可能性があるためUnsupportedOperationExceptionです。Arrays#asList()Collections#unmodifiableList()

このすべてを担当する(および) コンポーネントのMenuRenderer背後にあるレンダラーであるは、デフォルトで、コレクションの に基づいてコレクションの新しいインスタンスを作成します。これは、エンティティのコレクション プロパティを満たすために Hibernate によって内部的に使用されるHibernate の実装を返す場合に失敗します。つまり、メソッドは現在のセッションを介して基礎となるプロキシを初期化する必要がありますが、ジョブはトランザクション サービス メソッド内で実行されないため、何もありません。UISelectManyUISelectOnegetClass().newInstance()LazyInitializationExceptiongetClass()PersistentCollectionadd()

のこのデフォルトの動作をオーバーライドするには、コンポーネントの属性を介して目的のコレクション タイプの FQNを明示的にMenuRenderer指定する必要があります。プロパティの場合は指定し、プロパティの場合は指定します(または順序が重要でない場合):collectionTypeUISelectManyListjava.util.ArrayListSetjava.util.LinkedHashSetjava.util.HashSet

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

UISelectMany同じことが、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">

とりわけ<h:selectManyMenu>の VDL ドキュメントも参照してください。残念ながら、これは のVDL ドキュメントで<p:selectManyMenu>は指定されていませんが、変換に同じレンダラーを使用しているため、動作するはずです。IDE が不明なcollectionType属性をぎくしゃくして、それを無視して実行すると機能するのに迷惑な下線を引く場合は、<f:attribute>代わりに使用してください。

<p:selectManyMenu ... >
    <f:attribute name="collectionType" value="java.util.LinkedHashSet" />
    ...
</p:selectManyMenu>
于 2014-08-11T17:58:51.567 に答える