Hibernate的延迟加载.docx

上传人:M****1 文档编号:552241547 上传时间:2023-04-08 格式:DOCX 页数:7 大小:404.11KB
返回 下载 相关 举报
Hibernate的延迟加载.docx_第1页
第1页 / 共7页
Hibernate的延迟加载.docx_第2页
第2页 / 共7页
Hibernate的延迟加载.docx_第3页
第3页 / 共7页
Hibernate的延迟加载.docx_第4页
第4页 / 共7页
Hibernate的延迟加载.docx_第5页
第5页 / 共7页
点击查看更多>>
资源描述

《Hibernate的延迟加载.docx》由会员分享,可在线阅读,更多相关《Hibernate的延迟加载.docx(7页珍藏版)》请在金锄头文库上搜索。

1、Hibernate_Query_iterate的延迟加载1:通过Query接口的list()方法获取所有对象,然后调用Sesssion.delete(Obj)来删除对象2:通过Query接口的iterate()方法获取Iterator来迭代每个对象分别调用Sesssion.delete(Obj)来删除对象分析:Query.list()方法通过一条select语句来查询整个表来得到所以对象,且获得的对象是完整的.而Query.iterate()方法执行后,发出第一条select语句,只查询表的ID的一列!Entities returned as results are initialized o

2、n demand. The first SQL query returns identifiers only.对于每个对象,通过Sesssion.delete(Obj)来删除对象并,要先获取整个对象,当且仅当此时,才发出SQL语句来查询目标对象(行).只有当你对iterate()中的对象进行操作时,Hibernate才会向数据库再次发送SQL语句来获取该对象属性值.这就是Hibernate的”延迟加载”,” initialized on demand”并延迟加载时,Session不能被关闭,就是说如果Session被关闭了后,延迟加载就会抛出异常: org.hibernate.LazyInit

3、ializationException: could not initialize proxy - no Sessionat org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:167)at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:215)at org.hibernate.proxy.pojo.javassist.JavassistLazy

4、Initializer.invoke(JavassistLazyInitializer.java:190)at beans.People_$_javassist_0.toString(People_$_javassist_0.java)1:SRC1/Session session = sessionFactory.openSession();Transaction tx = session.beginTransaction();Query query = session.createQuery(from People);Iterator iter = query.iterate();Peopl

5、e people = (People)iter.next();System.out.println(“-“);System.out.println(people);mit();session.close();/执行结果:通过Debug单步运行,我们会发现 查询people的SQL语句 是在System.out.println(people)执行时才发出的!为什么最终查询people的语句是在System.out.println(people)执行时才出发的?分析:(因为Query.iterate()返回的结果是延迟加载的)People people = (People)iter.next();

6、因为people会被延迟到其真正被使用时才加载.所以上面这一句执行后,people还没有被加载的.System.out.println(people);就在这一句才真正用到people,所以此时才会数据库发出SQL语句/2:SRC2/Session session = sessionFactory.openSession();Transaction tx = session.beginTransaction();Query query = session.createQuery(from People);Iterator iter = query.iterate();People people

7、 = (People)iter.next();System.out.println(“-“);mit();session.close();System.out.println(people);/执行结果:程序抛出org.hibernate.LazyInitializationException: could not initialize proxy - no Session 异常!System.out.println(people);执行到这一句时,程序的延迟初始化被执行!但因为此时Session已关闭(JDBC的Connection已被关闭)所以无法发出SQL语句,所以抛出异常!Query.

8、iterate()的延迟初始化深入分析(又是动态代理)在SRC1中, People people = (People)iter.next();这一句执行完后,实际查询people的语句还未发出,但people引用的实例是什么呢?看图: 这个对象中的也有People类的所以字段,看看,还有一个handler字段,就是动态代理了嘛,是javassist直接生成字节码来生成的代理类: People_$_javassist_0调用people.toString()后,流程来到: JavassistLazyInitialize.invoke(proxy,thisMethod,proceed,args)方

9、法此时,thisMethod: public java.lang.String beans.People.toString()proceed: public final java.lang.String beans.People_$_javassist_0._d26toString()public Object invoke(final Object proxy,final Method thisMethod,final Method proceed,final Object args) throws Throwable if ( this.constructed ) Object resul

10、t;try /对要调用的方法进行分类,部分类型的方法直接执行,否则/返回INVOKE_IMPLEMENTATIONresult = this.invoke( thisMethod, args, proxy );catch ( Throwable t ) throw new Exception( t.getCause() );if ( result = INVOKE_IMPLEMENTATION ) /初始化目标:(延迟加载的关键),就在此时才发出SQL语句/第一次访问代理类时,从数据库加载目标对象;/第二次访问代理类或以后时,直接返回Object target = getImplementat

11、ion();final Object returnValue;try if ( ReflectHelper.isPublic( persistentClass, thisMethod ) ) if ( !thisMethod.getDeclaringClass().isInstance( target ) ) throw new ClassCastException( target.getClass().getName() );/目标被加载后,调用对应的方法(这里是toString()returnValue = thisMethod.invoke( target, args );else if

12、 ( !thisMethod.isAccessible() ) thisMethod.setAccessible( true );returnValue = thisMethod.invoke( target, args );return returnValue = target ? proxy : returnValue;catch ( InvocationTargetException ite ) throw ite.getTargetException();/如果方法在result = this.invoke( thisMethod, args, proxy );/已执行,直接返回结果e

13、lse return result;else / while constructor is runningif ( thisMethod.getName().equals( getHibernateLazyInitializer ) ) return this;else return proceed.invoke( proxy, args );总结: 原理和JDK的动态代理没什么太多的区别,这可以被称为”延迟加载代理”吧,1,这个代理继承了被代理的类(目标类target)2,当这个代理第一次被访问时,它会先访问数据库来生成目标的实例,然后再调用目标对象上对应的方法.3,当第二次访问这个代理时,因为目标已被加载,所以不用重新加载,直接访问目标上的方法(用反射的Method)一句话概括: 取得的对象实例上是它的代理,当且仅当访问第一次访问这个代理时,它才会加载被代理的目标

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 办公文档 > 解决方案

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号