@ManyToMany(fetch=LAZY) 上的 selectManyCheckbox 中的 LazyInitializationException [英] LazyInitializationException in selectManyCheckbox on @ManyToMany(fetch=LAZY)

查看:20
本文介绍了@ManyToMany(fetch=LAZY) 上的 selectManyCheckbox 中的 LazyInitializationException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当您需要填充 JPA M:N 关系时,处理多个 chackbox 的最佳方法是什么……例如,我有一个 JPA 实体硬件和实体连接.

What is the best way to handle multiple chackboxes when you nead to fill a JPA M:N relation ... for example I have an JPA entity Hardware and the entity Connectivity.

硬件有一组连接:

private Set<Connectivity> connectivities = new HashSet<Connectivity>(0);

并且有一个像这样的 setter 和 getter:

and has a setter and getter like this :

@ManyToMany(fetch = FetchType.LAZY, cascade = { CascadeType.PERSIST, CascadeType.REFRESH }, mappedBy = "hwProviders")
    public Set<Connectivity> getConnectivities() {
        return this.connectivities;
    }

    public void setConnectivities(Set<Connectivity> connectivities) {
        this.connectivities = connectivities;
    }

我在我拥有的 gui 中使用 JSF2.2 和 primefaces 5.3:

I'm using JSF2.2 and primefaces 5.3 in the gui I have:

<p:selectManyCheckbox id="connectivity" value="#{hardware.connectivities}" converter="omnifaces.SelectItemsConverter" layout="pageDirection">
     <f:selectItems value="#{connectivityes}" var="connect" itemValue="#{connect}" itemLabel="#{connect.name}"/>
</p:selectManyCheckbox>

即使我在渲染视图之前调用强制加载集合,我也有延迟异常的问题:

I have problem with lazy exception even if I make a call to force load the set before rendering the view:

hardware.getConnectivities().size();

有关如何处理这种情况的任何建议?

Any suggiestions on how to handle this situation?

我正在使用 omnifaces 进行实体转换.

I'm using omnifaces to make the entity conversion.

Tnx 到 BalusC 我已经设法正确加载,但我仍然有问题 wuth 保存.当我选中复选框并提交表单时,我认为转换中出现了惰性异常:

Tnx to BalusC I have managed to do the loading right but I still have problem wuth saving. When I select the checkbox and submit the form I get the lazy exception in conversion I think:

16:34:50,538 SEVERE [javax.enterprise.resource.webcontainer.jsf.context] (default task-12) org.hibernate.LazyInitializationException: failed to lazily initialize a collection, could not initialize proxy - no Session
    at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:575)
    at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:214)
    at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:554)
    at org.hibernate.collection.internal.PersistentSet.add(PersistentSet.java:202)
    at com.sun.faces.renderkit.html_basic.MenuRenderer.convertSelectManyValuesForModel(MenuRenderer.java:381)
    at com.sun.faces.renderkit.html_basic.MenuRenderer.convertSelectManyValue(MenuRenderer.java:128)
    at com.sun.faces.renderkit.html_basic.MenuRenderer.getConvertedValue(MenuRenderer.java:314)
    at org.primefaces.component.selectmanycheckbox.SelectManyCheckboxRenderer.getConvertedValue(SelectManyCheckboxRenderer.java:39)
    at javax.faces.component.UIInput.getConvertedValue(UIInput.java:1045)
    at javax.faces.component.UIInput.validate(UIInput.java:975)
    at javax.faces.component.UIInput.executeValidate(UIInput.java:1248)
    at javax.faces.component.UIInput.processValidators(UIInput.java:712)
    at javax.faces.component.UIForm.processValidators(UIForm.java:253)
    at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1260)
    at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1260)
    at javax.faces.component.UIViewRoot.processValidators(UIViewRoot.java:1195)
    at com.sun.faces.lifecycle.ProcessValidationsPhase.execute(ProcessValidationsPhase.java:76)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
    at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:198)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:646)
    at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:85)
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:130)
    at si.arctur.filter.SessionFilter.doFilter(SessionFilter.java:76)
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:60)
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:132)
    at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:85)
    at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:61)
    at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
    at org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:131)
    at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:56)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:45)
    at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:63)
    at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:58)
    at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:70)
    at io.undertow.security.handlers.SecurityInitialHandler.handleRequest(SecurityInitialHandler.java:76)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    at org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:261)
    at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:247)
    at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:76)
    at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:166)
    at io.undertow.server.Connectors.executeRootHandler(Connectors.java:197)
    at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:759)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)

推荐答案

您需要在事务内部(因此,在服务方法内部)获取它,并且在事务外部(因此,例如在 JSF 托管 bean init/action 方法中),因此会抛出 LazyInitializationException.

You need to fetch it while inside a transaction (thus, inside the service method), and not while outside a transaction (thus, inside e.g. JSF managed bean init/action method), that would thus throw a LazyInitializationException.

所以,你的尝试

hardware.getConnectivities().size();

必须发生在交易中.如有必要,创建一个新的服务方法,以便传递之前在另一个事务中获得的实体.

has to take place inside a transaction. Create if necessary a new service method for the purpose whereby you pass the entity which was obtained before in another transaction.

hardwareService.fetchConnectivities(hardware);

public void fetchConnectivities(Hardware hardware) {
    hardware.setConnectivities(em.merge(hardware).getConnectivities()); // Becomes managed.
    hardware.getConnectivities().size(); // Triggers lazy initialization.
}

另一种方法是创建一个 DTO,用于急切获取它的目的.

An alternative would be to create a DTO for the purpose which has it eagerly fetched.

然后要保存所选项目,请确保将选择组件的 collectionType 属性显式指定为标准 Java 类型,而不是让它自动发现 JPA impl 特定的延迟加载类型,例如 org.hibernate.collection.internal.PersistentSet 在您的特定情况下.JSF 需要它,以便在使用所选项目填充集合之前实例化集合.

And then to save the selected items, make sure that you explicitly specify the selection component's collectionType attribute to a standard Java type rather than letting it autodiscover a JPA impl specific lazy loaded type such as org.hibernate.collection.internal.PersistentSet in your specific case. JSF needs it in order to instantiate the collection before filling it with the selected items.

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

另见 org.hibernate.LazyInitializationException at com.sun.faces.renderkit.html_basic.MenuRenderer.convertSelectManyValuesForModel.

这篇关于@ManyToMany(fetch=LAZY) 上的 selectManyCheckbox 中的 LazyInitializationException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆