2012-03-03 255 views
1

我试图解决我的LazyLoading问题,这是我在过去通过fetchType EAGER解决的问题。但这不可能是最终的解决方案。LazyLoading with spring and hibernate

我试图构造一个例子,它并不像它的样子很多,但是证明了我的问题: 我有一个公司,并且人们是@ManyToOne。 现在,当我试图通过计算器来访问personList,我得到这个异常:

Schwerwiegend [javax.enterprise.resource.webcontainer.jsf.context] (http--127.0.0.1-8080-4) javax.el.ELException: /tablePersons.xhtml @31,76 value=" #{calculator.getPersonCount(_var)}": 
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: business.domain.Company.personList, no session or session was closed 

也许有人可以帮我解决这个?

tablePersons.xhtml:

<p:dataTable var="_var" value="#{facade.companies}"> 
<p:column> 
<h:outputText value="#{calculator.getPersonCount(_var)}" /> 

背衬正面:

@Named 
@RequestScoped 
class Facade() { 
    @Inject 
    Dao dao; 

    List<Company> companies; 

    @PostConstruct 
    init() { 
     companies = Dao.findByNamedQuery("Companies.ALL"); 
    } 
} 


@Named 
@RequestScoped 
class Calculator { 
    int getPersonCount(Company c) { 
     return c.getPersonList().size(); //EX 
    } 
} 

服务界面污物:

@Stateless 
@Transactional 
class Dao() { 
    @PersistenceContext 
    private EntityManager em; 

    //CRUD 
} 

实体:

@Entity 
@NamedQueries({ 
    @NamedQuery(name = Company.ALL", 
       query = "SELECT c FROM Company c") 
}) 
class Company { 
    @OneToMany(cascade = CascadeType.ALL) // fetch=FetchType.EAGER <-ugly, but would work 
    List<Person> personList = new LinkedList<Person>(); 
} 

我也已经配置了Spring OpenEntityManager在web.xml:

<filter> 
    <filter-name>OpenEntityManagerInViewFilter</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> 
</filter> 
<filter-mapping> 
    <filter-name>OpenEntityManagerInViewFilter</filter-name> 
    <url-pattern>/*</url-pattern> 
</filter-mapping> 

但它不工作。但我不知道为什么! 也许有人知道更多?

tyvm

回答

1

为了解决LazyInitializationException发生在视图层,你有以下几种选择:

  1. 使用 “打开的EntityManager in View” 模式来延迟加载在视图中未初始化的实体。看来你正在这样做,但我不知道为什么它失败了。

  2. 在返回视图之前,始终初始化需要在视图中显示的所有实体。

您可以使用Hibernate.initialize()强制初始化Company.personList:

class Facade() { 
    @Inject 
    Dao dao; 

    List<Company> companies; 

    @PostConstruct 
    init() { 
     companies = Dao.findByNamedQuery("Companies.ALL"); 
     Hibernate.initialize(companies.getPersonList()); 
    } 
} 

或者使用fetch join与Company.It一起取personList会导致返回公司反对完全有自己的personList初始化。

@Entity 
@NamedQueries({ 
    @NamedQuery(name = "Company.ALL",query = "SELECT c FROM Company c") 
    @NamedQuery(name = "Company.ALL.WithPerson",query = "SELECT c FROM Company c join fetch c.personList") 
}) 
class Company { 
    @OneToMany(cascade = CascadeType.ALL) // fetch=FetchType.EAGER <-ugly, but would work 
    List<Person> personList = new LinkedList<Person>(); 
} 

然后使用命名查询“Company.ALL.WithPerson”

+1

人感谢您的回答,我真的很感激这个检索的公司!与此同时,我发现如果使用@PersistenceContext(type = PersistenceContextType.EXTENDED)'',它会起作用,但我不知道这是否是一种好的做法?否则,我会选择你的解决方案,并在postconstruct中进行初始化。 – membersound 2012-03-04 12:23:31

+0

不客气。我在'@PersistenceContext(type = PersistenceContextType.EXTENDED)'没有太多经验。所以我不能评论它。但对于“在视图中打开EntityManager”或“在视图中打开会话”模式,我个人不赞成。你可以参考http://stackoverflow.com/questions/1103363/why-is-hibernate-open-session-in-view-considered-a-bad-practice – 2012-03-05 01:41:25

相关问题