hibernate配置延迟加载报:failed to lazily initialize a collection of role: com.ln.jtf.biz.dal.dao.pojos.Customer.cusaccounts, no session or session was closed。原因是web上get子表时session已经关闭。针对这个问题spring提供了解决方案,有两种方式:
一种是过滤器:OpenSessionInViewFilter,在web.xml文件中增加配置如下:
<filter>
<filter-name>hibernateFilter</filter-name>
<filter-class>
org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>hibernateFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
看一下代码实现:
protected void doFilterInternal(
HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
SessionFactory sessionFactory = lookupSessionFactory(request);
boolean participate = false;
if (isSingleSession()) {
// single session mode
if (TransactionSynchronizationManager.hasResource(sessionFactory)) {
// Do not modify the Session: just set the participate flag.
participate = true;
}
else {
logger.debug("Opening single Hibernate Session in OpenSessionInViewFilter");
Session session = getSession(sessionFactory);
TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session));
}
}
else {
// deferred close mode
if (SessionFactoryUtils.isDeferredCloseActive(sessionFactory)) {
// Do not modify deferred close: just set the participate flag.
participate = true;
}
else {
SessionFactoryUtils.initDeferredClose(sessionFactory);
}
}
//.....
}
通过ROOT WebApplicationContext已获取一个普通spring bean的方式来获取SessionFactory
protected SessionFactory lookupSessionFactory() {
if (logger.isDebugEnabled()) {
logger.debug("Using SessionFactory '" + getSessionFactoryBeanName() + "' for OpenSessionInViewFilter");
}
WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
return wac.getBean(getSessionFactoryBeanName(), SessionFactory.class);
}
再看如何获取到WebApplicationContext:
public static WebApplicationContext getWebApplicationContext(ServletContext sc, String attrName) {
Assert.notNull(sc, "ServletContext must not be null");
Object attr = sc.getAttribute(attrName);
if (attr == null) {
return null;
}
if (attr instanceof RuntimeException) {
throw (RuntimeException) attr;
}
if (attr instanceof Error) {
throw (Error) attr;
}
if (attr instanceof Exception) {
throw new IllegalStateException((Exception) attr);
}
if (!(attr instanceof WebApplicationContext)) {
throw new IllegalStateException("Context attribute is not of type WebApplicationContext: " + attr);
}
return (WebApplicationContext) attr;
}
其中attrName为:String ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE = WebApplicationContext.class.getName() + ".ROOT";
在某些配置下(?)由于根据这个attrName找不到对应的attr造成 sc.getAttribute(attrName)这个方法得到的是null,而报No WebApplicationContext found: no ContextLoaderListener registered?这个错误。
一种是配置拦截器:OpenSessionInViewInterceptor,在spring配置文件中增加如下(我使用的是Schema-based XML方式):
<mvc:interceptors>
<bean id="openSessionInViewInterceptor"
class="org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
</mvc:interceptors>
这样配置之后session将会保持。
看一下代码实现:
public void preHandle(WebRequest request) throws DataAccessException {
if ((isSingleSession() && TransactionSynchronizationManager.hasResource(getSessionFactory())) ||
SessionFactoryUtils.isDeferredCloseActive(getSessionFactory())) {
// Do not modify the Session: just mark the request accordingly.
String participateAttributeName = getParticipateAttributeName();
Integer count = (Integer) request.getAttribute(participateAttributeName, WebRequest.SCOPE_REQUEST);
int newCount = (count != null ? count + 1 : 1);
request.setAttribute(getParticipateAttributeName(), newCount, WebRequest.SCOPE_REQUEST);
}
else {
if (isSingleSession()) {
// single session mode
logger.debug("Opening single Hibernate Session in OpenSessionInViewInterceptor");
Session session = SessionFactoryUtils.getSession(
getSessionFactory(), getEntityInterceptor(), getJdbcExceptionTranslator());
applyFlushMode(session, false);
TransactionSynchronizationManager.bindResource(getSessionFactory(), new SessionHolder(session));
}
else {
// deferred close mode
SessionFactoryUtils.initDeferredClose(getSessionFactory());
}
}
}
可以看到在这里spring做了判断,如果当前请求线程中没有绑定session,那么就新创建一个,并且绑定到当前线程中。特别要提一下这里是通过HibernateAccessor这个InitializingBean来获取到SessionFactory的,和过滤器的方式不同。
分享到:
相关推荐
- `lazy="proxy"`:表示Hibernate将为`Dept`实体创建一个代理对象,只有当真正访问到`Dept`对象的相关属性时,Hibernate才会发起数据库查询,加载实际的`Dept`对象。 - `fetch="select"`:默认值,表示在查询`Emp`时...
当Hibernate加载一个实体时,默认不会立即加载其关联的实体或集合属性。相反,它会创建一个代理对象来表示这些属性。当程序试图访问这些属性时,Hibernate会在后台异步加载实际的数据。 #### 三、延迟加载的具体...
这是因为,如果不使用延迟加载,加载一个实体可能会导致所有相关联的实体都被加载到内存中,从而严重影响性能。 **配置方式:** 要启用集合类型的延迟加载,需要在映射文件中为集合元素添加`lazy="true"`属性,...
Hibernate利用Java的动态代理机制,为延迟加载的集合属性创建了一个代理对象。当我们尝试访问`addresses`时,实际上是在调用代理对象的方法,代理对象会检测到这个访问请求,然后触发实际的数据库查询,加载关联的`...
详细介绍hibernate延迟加载,对hibernate初学者有一定的帮助
在开发Flex与Hibernate集成的应用时,延迟加载(Lazy Loading)是一个常见的挑战,因为Flex客户端无法直接理解和处理Hibernate的延迟加载机制。延迟加载是一种优化策略,它允许关联的对象在真正需要时才被加载,而...
当使用Hibernate的`Session.load()`方法或在映射文件中设置了`lazy="true"`时,Hibernate并不会立即从数据库中获取关联对象的所有数据,而是创建一个代理对象。这个代理对象在需要访问其属性时才会执行实际的数据库...
其中一个关键问题是,延迟加载机制依赖于保持Session对象处于打开状态。这对于采用DAO(Data Access Object)模式,即试图将持久层逻辑与业务逻辑完全分离的设计来说,构成了挑战。 在DAO模式下,所有数据库操作,...
在代码片段`(1)`中,Hibernate不会立即加载`addresses`集合,而是返回一个代理集合。当代码片段`(2)`被执行,即迭代器开始遍历集合时,Hibernate才会执行必要的数据库查询,加载关联的地址信息。 ### 总结 通过...
Hibernate延迟加载机制.zip
在给定的文档中,我们看到一个例子,展示了如何在 Hibernate 中配置一个具有集合属性的实体类 `Person`,以及如何通过映射文件启用延迟加载。`Person` 类拥有一个 `Set<Address>` 类型的 `addresses` 属性,表示个人...
Hibernate作为Java领域中的一个强大的对象关系映射框架,提供了许多优化数据库操作的策略,其中之一便是延迟加载(Lazy Loading)。延迟加载机制旨在减少不必要的性能消耗,只在真正需要数据时才执行加载操作。本文...
- 如果没有显式设置 lazy="false",则默认情况下 Hibernate 使用 Select Fetching,这意味着对于每个主对象,Hibernate 都会发送一个 SQL 查询来加载关联对象。 - 这种方式适用于关联数据量不大,且每次查询都需要...
2. 当执行查询并返回实体时,如果关联对象标记为懒加载,Hibernate并不会立即执行SQL去获取关联数据,而是创建一个代理对象。这个代理对象会在真正访问关联属性时,通过执行额外的数据库查询来获取数据。 3. ...
**延迟加载**(Lazy Loading)是Hibernate框架中的一个重要特性,主要用于优化数据库操作,减少不必要的数据加载,从而提升应用程序的性能。在传统的Eager Loading(急切加载)模式下,一旦加载了一个对象,与之相关的...
3. **事务管理**:延时加载需要在一个有效的Hibernate Session内进行。在多层架构中,确保事务管理正确,尤其是在Service和DAO层之间,是确保延时加载成功的关键。 4. **N+1查询问题**:如果一个实体有多个关联属性...