延迟加载 ERROR org.hibernate.LazyInitializationException:42 - could not initialize proxy - ...

no Session问题,即延迟加载

延迟加载的问题是指当我们调用完action中的某个方法,在jsp页面要显示我们想要的信息的时候,发现在dao中打开的session已经关闭了。

如下图,第一个箭头表示的是我们通过前台页面返回action,action会通过service层调用dao去访问数据库,当从数据库中把值取出来之后返回到action中,再返回到前台页面中去。我们知道,只有我们在调用某个类getter()方法的时候才会打开session,可惜的是,在hibernateTemplate中注入的sessionFactory在action返回到前台页面前已经关闭了,也就是这个时候再前台页面调用getter()方法,想要打开session,但是sessionFactory已经关闭了,所以后台就会报错,显示no session。意思就是找不到session。

这个时候可以采用以下几种方式解决:

1、  将pojo类中的fetch的lazy改成eager,这个时候如果你的操作页面中牵扯了多个外键关系的话,就要把这几个外键关系的fetch的lazy都改成eager。这里的lazy是代表懒加载的意思,也就是说在查询一个表的信息的时候,不会把关联的表的信息查找出来。而如果改成eager的话,就代表说把关联的表的信息也全部加载出来。很明显,这样的操作会加载一些我们压根就不需要的操作,也可能我们只需要加载某张表的信息的时候,却自动的把关联的表加载出来。所以这种操作性能是很差的,不建议使用。

2、  配置过滤器openSessionInViewFilter,顾名思义,这个过滤器是指把在页面中打开session的服务,也就是说延迟session打开的状态,在前台页面中调用完方法之后再关闭session,配置如下:


<filter>

<filter-name>OpenSessionInView</filter-name>

<filter-class>

org.springframework.orm.hibernate3.support.OpenSessionInViewFilter

</filter-class>

</filter>

<filter-mapping>

<filter-name>OpenSessionInView</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

要注意的是这个过滤器要配置到struts的过滤器的前面,不然就不起作用了,因为配置在struts过滤器的后面的话,数据已经接收完毕了,也就是说sessionFactory已经关闭了,这个时候你再来配置说把session延长到view中,已经没作用了,所以要把openSessionInViewFilter配置在struts前面。 但是要注意的是,上面的配置并不是完整的配置,完整的配置应该是在filter里面配置如下信息:


<filter>

<filter-name>OpenSessionInView</filter-name>

<filter-class>

org.springframework.orm.hibernate3.support.OpenSessionInViewFilter

</filter-class>

<init-param>

                   <param-name>singleSession</param-name>

                   <param-value>true</param-value>

         </init-param>

</filter>

<filter-mapping>

<filter-name>OpenSessionInView</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

上面配置的意思是表示配置成单例的session。但是如果按以上配置的话,在后续session的操作中是会出现问题的,而如果不配置成单例的话,性能是很低的。所以这个方法也不建议。

3、  手工操作(建议)

a)   在action中操作

在action中操作指的是我们在传递对象到前台页面(这里主要是jsp)的时候,多传递一些对象到前台去。比如在action中我们需要传递question对象到前台中进行展示,但是同时也需要查找出这个问题所属的类型type,这个时候就可以在页action中除了传递question对象之外,再根据这个question的其他属性(如tid)来查找到对应的type,再把type对象传递到页面中。不过这样做比较麻烦的是除了自己要在dao中加方法外,如果一个页面管理着好几个数据表的话,传递的对象属性相对就比较多了。

b)   在daoimpl中操作(强烈建议)

在daoimpl中进行手工设置是本人觉得最合适的方式,也是比较推崇的一种。用这种方法的话,在daoimpl的操作中,就要用到hibernateCallback的内部类方法了。也就是说调用super.getHibernateTemplate().execute()方法,编写内部类,在得到一个list集合之后,取出集合的对象,调用要用到的关联类的getter()方法,就可以打开session了,一般不用调用主键的getter()方法。

范例:


public Question findById(final Integer id) throws Exception {

return super.getHibernateTemplate().execute(

new HibernateCallback<Question>() {

@SuppressWarnings("unchecked")

public Question doInHibernate(Session session)

throws HibernateException, SQLException { // 用hibernateCallBack

String hql = "From Question AS q WHERE q.qid=?"; // 构建hql语句

Query query = session.createQuery(hql); // 创建query

query.setInteger(0, id); // 设置占位符

List<Question> all = query.list(); // 得到具体的list集合,里面只存放一个question对象

if (all.size() > 0) { // 集合不为空

Question vo = all.get(0); // 取出question对象

vo.getType().getTitle();

// 调用type 的getTitle 方法,这样会把type 相关的session 打开,在jsp 调用时数据还可以调用

vo.getAnswers().size();

// 调用getAnswers() 方法,把session 打开,消除延迟加载

if (vo.getAnswer() != null) { // 如果存在最佳答案

vo.getAnswer().getContent(); // 消除延迟加载

                                                                 }

return vo; // 返回vo

}

return null;

}

});

}

时间: 2024-10-13 18:18:32

延迟加载 ERROR org.hibernate.LazyInitializationException:42 - could not initialize proxy - ...的相关文章

ssh框架错误:org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role。

在做ssh项目练习的时候出现问题: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role 原因在于hibernate的懒加载出现的问题.在多方中的一方的配置没有指定加载方式,而且一方中的多方是懒加载,因此在获取一方的时候一方是获取到了,但是再获取多方的时候session已经关闭了,这时候会获取不到多方信息,因此报错. 解决办法: 将一方中的多方(one-to-many

懒加载异常 org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role

@OneToMany(cascade={CascadeType.REFRESH,CascadeType.REMOVE},mappedBy="parent",fetch=FetchType.EAGER) private Set<ProductType> childTypes = new HashSet<ProductType>(); 这个是懒加载异常,就是在查询时没有加载关联表的对象,你读取这个关联对象的时候,hibernate的session已经关闭,所以无法获

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role

这个是懒加载异常,就是在查询时没有加载关联表的对象,你读取这个关联对象的时候,hibernate的session已经关闭,所以无法获取对象.可以在配置文件里关闭懒加载 lazily=false 使用事务 @Override @Transactional public void run(ApplicationArguments args) throws Exception { initOrders(); findOrders(); } @SpringBootApplication @EnableJ

org.hibernate.LazyInitializationException

1.org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.chen.vo.Teacher.students, no session or session was closed 异常描述:运行以下方法出现.注:持久类Teacher与Student呈多对多关联. @Test//fail public void query2(){ List list = hibe

【bug记录】jpa 解决org.hibernate.lazyinitializationexception could not initialize proxy - no session

前言 最近开发项目比较忙,springcloud的笔记得稍稍放放了,下午出来个bug,恶心的不行,功能很简单,也没有什么级联或复杂的映射关系,就是一直在报三个异常 Caused by: com.fasterxml.jackson.databind.JsonMappingException: No serializer found for class org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer and no propert

org.hibernate.LazyInitializationException: could not initialize proxy - no Session

在<many-to-on>中这错误很常见,字面意义就是不能被初始化,因为session已经关闭了. 简单理解就是因为,你使用了lazy=true,这样hibernate在从数据库中调数据的时候是不会把关联的对象查出来的,而是保存一个获取值得方法,在你使用getXXX()调用的时候,hiberante会利用这个保存的方法去从数据库中取数据.而往往我们在jsp页面中使用getXXX()准备展示数据的时候,session早已经在dao中就关闭了,我们该如何解决这种异常呢? 简单的说有三种:1.把la

懒加载异常org.hibernate.LazyInitializationException: could not initialize proxy - no Session

错误页面提示 could not initialize proxy - no Session 控制台 org.hibernate.LazyInitializationException: could not initialize proxy - no Session 病症:这是一个lazy使用后的Exception,使用迟时加载,在session(hibernate里的session),关闭后使用该对象的未加载变量,也就是说session已经关闭,没有保存到内存中,然后你使用了,导致该异常. Q

Hibernate 异常org.hibernate.LazyInitializationException: could not ini...

错误页面提示 could not initialize proxy - no Session 控制台 org.hibernate.LazyInitializationException: could not initialize proxy - no Session 病症:这是一个lazy使用后的Exception,使用迟时加载,在session(hibernate里的session),关闭后使用该对象的未加载变量,也就是说session已经关闭,没有保存到内存中,然后你使用了,导致该异常. Q

ssh中懒加载问题org.hibernate.LazyInitializationException

当 出现上诉异常时多半是因为service层得到的对象关联到多个对象,而在service层中未将其余对象实例化.如一个班级有多个学生,在service层中只将班级查出来.问题的出现是在显示层中迭代调用班级中的学生的时候就会报org.hibernate.LazyInitializationException,因为此时session已经关闭,而还会用到学生的代理对象.解决办法有两种:一是用OpenSessionInViewFilter(需要注意将它配置在struts2的过滤器之前):方法二是在ser