关于使用hibernate出现org.hibernate.LazyInitializationException: could not initialize proxy - no Session错误
2015-11-14 16:32
525 查看
hibernate3中出现 could not initialize proxy - no Session 错误的解决办法以及lazy load的介绍 could not initialize proxy - no Session
异常:
org.hibernate.LazyInitializationException: could not initialize proxy - no Session
at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:57)
at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:111)
原因:hibernate3 many-to-one的默认选项是 lazy = "proxy"
解决方法:<many-to-one> & <set> 中设置 lazy="false"
错误代码:
role.hbm.xml文件的配置
rolePrivate.hbm.xml
在代码的DAO方法中
这个dao操作后,返回的是一个UserRole的集合,集合中,role对应的实体类并没有从数据库中得到数据,而是被赋予了一个状态句柄org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer
标明当再次使用的时候查询。
而当再次使用userRole的get方法的时候,此时session已经被关闭了,因此就会报错。
后面是查到的资料
HIBERNATE的持久化对象加载策略。
延迟加载, 也就是用到的时候才去加载.这样可以提高一些性能.
Hibernate的lazy loading 采用了一个HibernateSession来管理session,它的逻辑是每进行一次数据库操作,就开新的session,操作完成后立即关闭该session。这样做的好处是可以严格关闭session,避免菜鸟级的错误,但是hibernate.org并不推荐这么做。因为这不适合lazy
loading,也不适合跨方法的事务。
比如在我们的应用中,user->post形成一对多的映射,User中有一个包含post的List。
在User中,有多个属性:name,password,phone等,还有一个List类型的posts。当我们对posts使用lazy laoding的时候,hibernate会在获得User对象的时候,仅仅返回name,password,phone等基本属性,当你访问posts的时候,它才会从数据库中提取posts需要的数据,这就是所谓lazy
laoding。但是在我们的系统中,session是被立即关闭的,也就是在读取了name,password,phone等基本属性后,session已经close了,再进行lazy loaiding就会有异常。
解决办法是在close session之前,调用Hibernate.initialize(user.getPosts()),告诉系统,user.getPosts()是需要lazy laoding的。但是这样做会破坏HibernateSession类的封装.
后来采用所谓的OpenSessionInView模式,把session的周期交给servlet filter来管理,每当有request进来,就打开一个session,response结束之后再关闭它,这样可以让session存在于整个请求周期中。
Hibernate中Lazy延迟加载
Hibernate有关one-to-one和many-to-one在查询中的父亲端lazy问题
Hibernate3在关联上有lazy这个属性,如果是Hibernate2,应该是设置outer-join="false",然后被关联的对象,在class那个地方设置lazy="true".首先,对于many-to-one的问题,可以在父亲端的class标签中设置lazy来解决,这样,在查询儿子的时候,不会发送多余的sql
.
对于one-to-one,在hibernate2里面,由于one-to-one里面没有lazy的选项,所以只能通过设置outer-join="false"来解决。而hibernate3已经加入了lazy,所以不会有这个问题。
总体来说,如果你发现你查询儿子的时候,有多余的sql发送,那一定是你对hibernate的误用..
在hibernate 的one-to-many,many-to-one,many-to-many中,为了效率的提高,我们一般都采用lazy机制,但使用spring的getHibernateTemplate().save(Object)时,HibernateTemplate试图每次在execute之前去获得Session,执行完就力争关闭Session
。也就是说Hibernate的Lazy初始化1:n关系时,你必须保证是在同一个Session内部使用这个关系集合,不然Hiernate将抛出Failed to lazily initialize a collection - no session or session was closed的例外。
Hibernate中的对象的关联(association)的设置还是不够灵活,实际应用中有的地方需要lazy load,有的地方又不需要,其实还有的地方就根本不需要使用association。而在Hibernate中,只能在影射文件中设置一种方式,像我们这样的应用,我是不敢轻易使用open
session in view的(慢点总比lock住要好),只能是要么不设置association,要么就是lazy=true的。以前的分类信息只用了一个many to one的关系,代价还可以忍受,但现在关系越来越复杂了,再多加几个的话,所要付出的performance,带宽等方面的代价恐怕就不能忽略了,即使使用cache提高一点performance,对带宽的浪费也还是不可原谅的。
异常:
org.hibernate.LazyInitializationException: could not initialize proxy - no Session
at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:57)
at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:111)
原因:hibernate3 many-to-one的默认选项是 lazy = "proxy"
解决方法:<many-to-one> & <set> 中设置 lazy="false"
错误代码:
role.hbm.xml文件的配置
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <!-- Role实体类与数据库当中的ROLE表的映射关系 --> <hibernate-mapping package="cn.taxmanager.role.entity"> <class name="Role" table="ROLE" > <!-- 主键ID映射 --> <id name="roleId" column="ROLE_ID" length="32"> <generator class="uuid"></generator> </id> <!-- 角色名、角色状态映射 --> <property name="roleName" type="string"> <column name="ROLE_NAME" length="20" not-null="true"></column> </property> <property name="roleState" type="string"> <column name="ROLE_STATE" length="1"></column> </property> <!-- 角色与权限ID的映射对应关系 --> <set name="rolePrivileges" lazy="false" cascade="save-update,delete" inverse="true"> <key> <column name="ROLE_ID" not-null="true"></column> </key> <one-to-many class="RolePrivilege"/> </set> </class> </hibernate-mapping>
rolePrivate.hbm.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <!-- RolePrivilege实体类与数据库当中的ROLE表的映射关系 --> <hibernate-mapping package="cn.taxmanager.role.entity"> <class name="RolePrivilege" table="ROLE_PRIVILEGE"> <!-- 使用联合主键 --> <composite-id name="rolePrivilegeId" class="RolePrivilegeId"> <key-many-to-one name="role" class="Role" <span style="color:#ff0000;">lazy="false"</span>> <column name="ROLE_ID"></column> </key-many-to-one> <key-property name="code" type="string"> <column name="CODE" length="50"></column> </key-property> </composite-id> </class> </hibernate-mapping>标注为红色的"lazy=falst"本来是没有的
在代码的DAO方法中
public List<UserRole> getUserRoleByUserId(Serializable id) { Query query = getSession().createQuery("FROM UserRole WHERE userRoleId.userId=?"); query.setParameter(0, id); return query.list(); }
这个dao操作后,返回的是一个UserRole的集合,集合中,role对应的实体类并没有从数据库中得到数据,而是被赋予了一个状态句柄org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer
标明当再次使用的时候查询。
而当再次使用userRole的get方法的时候,此时session已经被关闭了,因此就会报错。
后面是查到的资料
HIBERNATE的持久化对象加载策略。
延迟加载, 也就是用到的时候才去加载.这样可以提高一些性能.
Hibernate的lazy loading 采用了一个HibernateSession来管理session,它的逻辑是每进行一次数据库操作,就开新的session,操作完成后立即关闭该session。这样做的好处是可以严格关闭session,避免菜鸟级的错误,但是hibernate.org并不推荐这么做。因为这不适合lazy
loading,也不适合跨方法的事务。
比如在我们的应用中,user->post形成一对多的映射,User中有一个包含post的List。
在User中,有多个属性:name,password,phone等,还有一个List类型的posts。当我们对posts使用lazy laoding的时候,hibernate会在获得User对象的时候,仅仅返回name,password,phone等基本属性,当你访问posts的时候,它才会从数据库中提取posts需要的数据,这就是所谓lazy
laoding。但是在我们的系统中,session是被立即关闭的,也就是在读取了name,password,phone等基本属性后,session已经close了,再进行lazy loaiding就会有异常。
解决办法是在close session之前,调用Hibernate.initialize(user.getPosts()),告诉系统,user.getPosts()是需要lazy laoding的。但是这样做会破坏HibernateSession类的封装.
后来采用所谓的OpenSessionInView模式,把session的周期交给servlet filter来管理,每当有request进来,就打开一个session,response结束之后再关闭它,这样可以让session存在于整个请求周期中。
Hibernate中Lazy延迟加载
Hibernate有关one-to-one和many-to-one在查询中的父亲端lazy问题
Hibernate3在关联上有lazy这个属性,如果是Hibernate2,应该是设置outer-join="false",然后被关联的对象,在class那个地方设置lazy="true".首先,对于many-to-one的问题,可以在父亲端的class标签中设置lazy来解决,这样,在查询儿子的时候,不会发送多余的sql
.
对于one-to-one,在hibernate2里面,由于one-to-one里面没有lazy的选项,所以只能通过设置outer-join="false"来解决。而hibernate3已经加入了lazy,所以不会有这个问题。
总体来说,如果你发现你查询儿子的时候,有多余的sql发送,那一定是你对hibernate的误用..
在hibernate 的one-to-many,many-to-one,many-to-many中,为了效率的提高,我们一般都采用lazy机制,但使用spring的getHibernateTemplate().save(Object)时,HibernateTemplate试图每次在execute之前去获得Session,执行完就力争关闭Session
。也就是说Hibernate的Lazy初始化1:n关系时,你必须保证是在同一个Session内部使用这个关系集合,不然Hiernate将抛出Failed to lazily initialize a collection - no session or session was closed的例外。
Hibernate中的对象的关联(association)的设置还是不够灵活,实际应用中有的地方需要lazy load,有的地方又不需要,其实还有的地方就根本不需要使用association。而在Hibernate中,只能在影射文件中设置一种方式,像我们这样的应用,我是不敢轻易使用open
session in view的(慢点总比lock住要好),只能是要么不设置association,要么就是lazy=true的。以前的分类信息只用了一个many to one的关系,代价还可以忍受,但现在关系越来越复杂了,再多加几个的话,所要付出的performance,带宽等方面的代价恐怕就不能忽略了,即使使用cache提高一点performance,对带宽的浪费也还是不可原谅的。
相关文章推荐
- 动手动脑小程序——TryAndCatch
- WCF 简易教程 IIS配置(二)
- 爬爬爬之路:UI(四) 晃动响应 触摸响应 响应者链 显示动态图片
- 动手动脑-异常处理
- 关于Spring与WebSocket结合的简单例子
- Spark修炼之道(进阶篇)——Spark入门到精通:第五节 Spark编程模型(二)
- 2015Noip总结
- 论java底层native
- Java中使用AES加密的简单示例
- Unity中用到的C#补充(一)-C#基础
- KVM如何在线添加新硬盘到Linux虚拟机上
- android 语音识别 语音手电(一)
- 动手动脑及课堂作业
- C#中的try catch 和finally
- 当代世界经济的发展趋势
- http协议学习 记录
- VirtualBox安装Redhat9.0
- 经济体制改革面临的形势和任务
- 公共 DNS 服务器 IP 地址
- 我的博客开始