LazyInitializationException 与 SpringOpenEntityManagerInViewFilter

LazyInitializationException with SpringOpenEntityManagerInViewFilter

尽管我正在使用 SpringOpenEntityManagerInViewFilter,但我在获得一些结果后遇到了 LazyInitializationException。 谜团是为什么我得到第一个结果(行)是正确的,然后它变得疲倦并且我没有得到更多的结果。 我已经尝试了我在这里阅读的所有内容我几乎已经阅读了所有 post 在这里,我仍然被困在这里。 我是 Spring data jpa 的新手,我怀疑这可能是胡说八道 这些是我的文件:

web.xml

.....

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/spring-config/*.xml</param-value>
</context-param>
<filter>
    <filter-name>SpringOpenEntityManagerInViewFilter</filter-name>
    <filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
    <init-param>
        <param-name>entityManagerFactoryBeanName</param-name>
        <param-value>entityManagerFactory</param-value>
    </init-param>
    <init-param>
        <param-name>flushMode</param-name>
        <param-value>AUTO</param-value>
    </init-param>
    <init-param>
        <param-name>singleSession</param-name>
        <param-value>true</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>SpringOpenEntityManagerInViewFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>         </listener>
 <listener>
    <listener-class>com.sun.faces.config.ConfigureListener</listener-class>
</listener>

ApplicationContext.xml

<context:annotation-config />
  <jpa:repositories base-package="com.previsionx.web.repositories" />
  <!-- Scan for all of Spring components such as Spring Service -->
  <context:component-scan base-package="com.previsionx.web">      </context:component-scan>
<!-- Necessary to get the entity manager injected into the factory bean -->
 <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />    

<!-- Define Hibernate JPA Vendor Adapter -->
<bean id="jpaVendorAdapter"
    class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
    <property name="databasePlatform"
        value="org.hibernate.dialect.MySQLDialect" />
</bean> 

<!-- Entity Manager Factory -->
<bean id="entityManagerFactory"
    class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
    <property name="persistenceUnitName" value="previsionx"></property>
    <property name="jpaVendorAdapter" ref="jpaVendorAdapter" />
</bean>

<!-- Transaction Manager -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>

<!-- Detect @Transactional -->
<tx:annotation-driven transaction-manager="transactionManager" />

PoSrvc.java

@Transactional
public class PoSrvc implements IPoSrvc {

  @Autowired
  private IPoRepository poRepository;

  @Autowired
  private IPoBuRepository poBuRepository;

  @Override
  @Transactional
  public List<Po> getAllByBu(long buId) {
    Set<Po> poSet = new LinkedHashSet<Po>();
    poSet.addAll(poBuRepository.findPoByBuId(buId));
    poSet.addAll(poRepository.findByCreatorBuId(buId));
    List<Po> list = new LinkedList<Po>();
    list.addAll(poSet);
    return list;

  }

IPoRepository.java

public interface IPoRepository extends JpaRepository<Po,Long>{

  List<Po> findByCreatorBuId(long buId);
  Po findById(long id);

IPoBuRepository.java

public interface IPoBuRepository extends JpaRepository<PoBu, Long> {

  @Query("SELECT p FROM PoBu pb INNER JOIN pb.po p WHERE pb.po.id = p.id AND pb.bu.id=:id ORDER BY pb.po.ref")
  List<Po> findPoByBuId(@Param("id") long id);

ManagePo.java

@ManagedBean
@ViewScoped
public class ManagePO implements Serializable {
......
@ManagedProperty("#{poSrvc}")
@Autowired
private IPoSrvc poSrvc;

@ManagedProperty("#{buSrvc}")
@Autowired
private IBuSrvc buSrvc;

@PostConstruct
public void init(){
    this.readOnly=false;
    poList = poSrvc.getAllByBu(appcontext.getBuId());
  ........
 }

欢迎提出任何建议,因为我不知道还能做什么:(

非常感谢您

编辑: 异常跟踪

GRAVE: Error Rendering View[/secure/managepo.xhtml]
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.previsionx.entities.Po.PoBuList, could not initialize proxy - no Session
at     org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:572)
at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:212)
at org.hibernate.collection.internal.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:153)
at org.hibernate.collection.internal.PersistentBag.size(PersistentBag.java:278)
at javax.faces.model.ListDataModel.isRowAvailable(ListDataModel.java:109)
at javax.faces.model.ListDataModel.setRowIndex(ListDataModel.java:184)
at javax.faces.model.ListDataModel.setWrappedData(ListDataModel.java:219)
at javax.faces.model.ListDataModel.<init>(ListDataModel.java:78)
at com.sun.faces.facelets.component.UIRepeat.getDataModel(UIRepeat.java:263)
at com.sun.faces.facelets.component.UIRepeat.setIndex(UIRepeat.java:523)
at com.sun.faces.facelets.component.UIRepeat.process(UIRepeat.java:577)
at com.sun.faces.facelets.component.UIRepeat.encodeChildren(UIRepeat.java:1110)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1856)
at org.primefaces.component.column.Column.renderChildren(Column.java:304)
at org.primefaces.component.datatable.DataTableRenderer.encodeCell(DataTableRenderer.java:963)
at org.primefaces.component.datatable.DataTableRenderer.encodeRow(DataTableRenderer.java:919)
at org.primefaces.component.datatable.DataTableRenderer.encodeRows(DataTableRenderer.java:830)
at org.primefaces.component.datatable.DataTableRenderer.encodeTbody(DataTableRenderer.java:777)
at org.primefaces.component.datatable.DataTableRenderer.encodeTbody(DataTableRenderer.java:740)
at org.primefaces.component.datatable.feature.PageFeature.encode(PageFeature.java:36)
at org.primefaces.component.datatable.DataTableRenderer.encodeEnd(DataTableRenderer.java:78)
at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:919)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1863)
at com.sun.faces.context.PartialViewContextImpl$PhaseAwareVisitCallback.visit(PartialViewContextImpl.java:582)
at com.sun.faces.component.visit.PartialVisitContext.invokeVisitCallback(PartialVisitContext.java:183)
at org.primefaces.component.api.UIData.visitTree(UIData.java:692)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700)
at javax.faces.component.UIForm.visitTree(UIForm.java:371)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700)
at com.sun.faces.context.PartialViewContextImpl.processComponents(PartialViewContextImpl.java:403)
at com.sun.faces.context.PartialViewContextImpl.processPartial(PartialViewContextImpl.java:322)
at org.primefaces.context.PrimePartialViewContext.processPartial(PrimePartialViewContext.java:60)
at javax.faces.component.UIViewRoot.encodeChildren(UIViewRoot.java:1004)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1856)
at com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:430)
at com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:133)
at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:120)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:219)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:647)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at com.previsionx.web.utils.NoCacheFilter.doFilter(NoCacheFilter.java:33)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter.doFilterInternal(OpenEntityManagerInViewFilter.java:177)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:108)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1041)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:603)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)

我已经使用 Primefaces Lazy 数据解决了table

问题似乎是一旦页面呈现,休眠会话就会关闭。

Service、repository 和 manageBean 发生了一些变化

服务:

@Component
public class PoSrvc implements IPoSrvc {

  @Autowired
  private IPoBuRepository poBuRepository;

  @Override
  @Transactional
  public List<Po> getAllByBu(long buId, int page, int results, String sort, SortOrder sortOrder) {
      Pageable pageable = new PageRequest(
              page, results,new Sort(new Order(SortOrder.ASCENDING.equals(sortOrder)? Direction.ASC: Direction.DESC, "po."+sort))
            );      
      return poBuRepository.findPoByBuId(buId,pageable);
  }

  @Override
  public int getCountAllByBu(long buId) {
      return poBuRepository.findCountAllByBuId(buId);
  }

存储库:

public interface IPoBuRepository extends JpaRepository<PoBu, Long> {


  @Query("SELECT DISTINCT po FROM PoBu pb WHERE (pb.bu.id=:id OR pb.po.creatorBu.id=:id) AND pb.po.deleted=false")
  List<Po> findPoByBuId(@Param("id") long id,Pageable pageable);

  @Query("SELECT COUNT (DISTINCT pb.po) FROM PoBu pb WHERE (pb.bu.id=:id OR pb.po.creatorBu.id=:id) AND pb.po.deleted=false")
  int findCountAllByBuId(@Param("id") long id);

还有我的 managedBean:

@ManagedBean
@ViewScoped
public class ManagePO implements Serializable {

  private static final long serialVersionUID = 8947292155668339391L;


  @ManagedProperty(value="#{appContext}") 
  private AppContext appcontext;
  @ManagedProperty("#{poSrvc}")
  private IPoSrvc poSrvc;

  private LazyDataModel<Po> lazyModel;

  @PostConstruct
  public void init(){
    this.readOnly=false;
    this.lazyModel = new LazyPoDataModel(appcontext.getBuId(), poSrvc);

最后这个 Lazy table 模型:

public class LazyPoDataModel extends LazyDataModel<Po> {
  private static final long serialVersionUID = 1L;
  private long buId;
  private IPoSrvc poSrvc;

  public LazyPoDataModel(long buId, IPoSrvc poSrvc) {
    super();
    this.buId = buId;
    this.poSrvc = poSrvc;
    this.setRowCount(this.poSrvc.getCountAllByBu(buId));
  }

  @Override
  public List<Po> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String,Object> filters) {
      List<Po> data = new LinkedList<Po>();
      int page = first/pageSize;

      if(sortField==null){
            sortField = "ref";
      }
      data=poSrvc.getAllByBu(buId, page, pageSize, sortField, sortOrder);

      return data;
  }

现在不再抛出 LazyInitializationException 了!!! 感谢提供线索!

编辑: XHTML:

<p:dataTable id="po_tbl" value="#{managePO.lazyModel}" styleClass="order-table" headerClass="order-table-header" rowClasses="order-table-odd-row,order-table-even-row" var="po"  style="width:1000px;"
            resizableColumns="true" paginator="true" 
                     paginatorTemplate="{CurrentPageReport}  {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
                     rowsPerPageTemplate="10,20,30,50"  rows="10" lazy="true">
            <p:column sortBy="#{po.ref}">
                <!-- column header -->
                <f:facet name="header">#{msg['tbl_hdr_po.manage_po']}</f:facet>
                <!-- row record -->
                <h:outputText value="#{po.ref}" />                  
            </p:column>

            <p:column styleClass="text-right">
                <f:facet name="header">#{msg['tbl_hdr_total.manage_po']}</f:facet>
                <h:outputText value="#{po.weight} #{po.weightUnit}" />
            </p:column>

            <p:column sortBy="#{po.product}">
                <f:facet name="header">#{msg['tbl_hdr_product.manage_po']}</f:facet>
                #{po.product}
            </p:column>
            <p:column sortBy="#{po.creatorBu.ref}">
                <f:facet name="header">#{msg['tbl_hdr_creator.manage_po']}</f:facet>
                #{po.creatorBu.ref}
            </p:column>