我正在尝试解决我的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
答案 0 :(得分:2)
要解决视图图层中出现的LazyInitializationException
,您有以下选项:
使用“在视图中打开EntityManager”模式来延迟加载视图中未初始化的实体。看起来你是这样做的,但我不知道它为什么会失败。
在返回视图之前,始终初始化视图中需要显示的所有实体。
您可以使用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”
检索公司