【问题标题】:LazyLoading with spring and hibernate使用spring和hibernate进行延迟加载
【发布时间】:2012-03-03 14:42:30
【问题描述】:

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

我试图构建一个示例,但它并没有多大意义,但它证明了我的问题: 我有一家公司,人员组成为@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>();
}

我也已经在 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

【问题讨论】:

    标签: java spring hibernate jsf


    【解决方案1】:

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

    1. 使用“Open 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 一起获取 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”检索公司

    【讨论】:

    • 谢谢你的回答,我真的很感激!!同时我发现如果我使用 @PersistenceContext(type=PersistenceContextType.EXTENDED) 会起作用,但我不知道这是否是一个好习惯?否则我会选择你的解决方案,在 postconstruct 中初始化。
    • 不客气。我在@PersistenceContext(type=PersistenceContextType.EXTENDED) 没有太多经验。所以我不能评论它。但是对于“Open EntityManager in View”或者“Open Session in View”模式,我个人不太赞成。可以参考stackoverflow.com/questions/1103363/…
    猜你喜欢
    • 2011-05-11
    • 2012-01-24
    • 1970-01-01
    • 2011-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-20
    • 1970-01-01
    相关资源
    最近更新 更多