延迟加载弹簧和休眠

时间:2012-03-03 14:42:30

标签: java spring hibernate jsf

我正在尝试解决我的LazyLoading问题,我过去常常使用fetchType EAGER解决这个问题。但这不是最终解决方案。

我尝试构建一个示例,它不会像现在这样简单,但演示了我的问题: 我有一家公司,人员是@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
    }
}

Crud服务:

@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>();
}

我还在web.xml中配置了Spring OpenEntityManager:

<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 个答案:

答案 0 :(得分:2)

要解决视图图层中出现的LazyInitializationException,您有以下选项:

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

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

  3. 您可以使用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与公司一起获取personList。这将导致返回的Companies对象的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”

    检索公司