hibernate笔记: 关于懒加载和load()方法

来源:互联网 发布:电路图绘制软件protel 编辑:程序博客网 时间:2024/05/16 14:20

重点牢记

 

1.Load支持懒加载,get不支持懒加载。

2.lazy的生命周期与session相同,lazy加载必须依赖于session一直开启。

3.Hibernate lazy属性,在3.x后是默认打开的,在以前版本中默认是关闭的。

4.hibernate通过cjlib实现代理。

5.load方法加载出来的是代理对象。

6.可以利用Hibernate.initialize(emp)来初始化代理对象达到命中数据库

7.代理类在未命中数据库之前,他只有真实对象的ID属性,其他数据都是没有的

 

Empoyee.hbm.xml的配置

 

[xhtml] view plain copy
  1. <hibernate-mapping  
  2.  package="hiber.domain">  
  3.   
  4.  <class name="Employee" table="employees"  discriminator-value="0"  >  
  5.   <id name="id">  
  6.    <generator class="increment"/>  
  7.   </id>  
  8.   <property name="name" not-null="true"/>  
  9.   <many-to-one name="department" column="department_id" ></many-to-one>   
  10.  </class>  
  11.   
  12. </hibernate-mapping>  

Department.hbm.xml的配置

[xhtml] view plain copy
  1. <hibernate-mapping  
  2.     package="hiber.domain">  
  3.   
  4.     <class name="Department" table="departments"  discriminator-value="0" >  
  5.         <id name="id">  
  6.             <generator class="increment"/>  
  7.         </id>  
  8.         <property name="name" not-null="true"/>  
  9.     </class>  
  10.   
  11. </hibernate-mapping>  

 

测试(一):

 

[java] view plain copy
  1. public class Many2One {  
  2.   
  3.     /** 
  4.      * @param args 
  5.      */  
  6.     public static void main(String[] args) {  
  7.         add();  
  8.         Employee employee =query();  
  9.         System.out.println(employee.getDepartment().getName());//(1) 进行访问  
  10.     }  
  11.     /** 
  12.      * 添加一个Department 和Employee 以及它们之间的关联 
  13.      */  
  14.     static void add(){  
  15.         Session s =null;  
  16.         Transaction t = null;  
  17.         s=HiberUtil.getSession();  
  18.         t=s.beginTransaction();  
  19.           
  20.         Department department = new Department();  
  21.         department.setName("人事部");  
  22.           
  23.         Employee employee = new Employee();  
  24.         employee.setName("steve");  
  25.         employee.setDepartment(department);  
  26.           
  27.         s.save(department);  
  28.         s.save(employee);  
  29.               
  30.         t.commit();  
  31.         s.close();  
  32.     }  
  33.     /** 
  34.      * 使用load方法测试 懒加载的相关问题 
  35.      * @return 
  36.      */  
  37.     static Employee query(){  
  38.         Session s =null;  
  39.         Transaction t = null;  
  40.         s=HiberUtil.getSession();  
  41.         t=s.beginTransaction();   
  42.         Employee employee = (Employee)s.load(Employee.class1);          
  43.         t.commit();  
  44.         s.close();  
  45.         return employee;  
  46.     }  
  47.   
  48. }  

 

结果: 会报错

[java] view plain copy
  1. Hibernate: select max(id) from departments  
  2. Hibernate: select max(id) from employees  
  3. Hibernate: insert into departments (name, id) values (?, ?)  
  4. Hibernate: insert into employees (name, department_id, id) values (?, ?, ?)  
  5. Exception in thread "main" org.hibernate.LazyInitializationException: could not initialize proxy - no Session  
  6.     at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:132)  
  7.     at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:174)  
  8.     at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:190)  
  9.     at hiber.domain.Employee_
    _javassist_0.getDepartment(Employee_
    _javassist_0.java)  
  10.     at hiber.sth.Many2One.main(Many2One.java:17)  

 

 

结果分析: 

 当使用session中的load方法查询数据库中的记录时,我们返回的是一个代理对象,而不是真正需要的那个对象;例如数据库中存有个Employee表,我们有cn.binyulan.doman.Employee的领域对象,如果查询Id值为“200626313”的Employee employee = (Employee)session.load(Employee.class,"200626313"),然后我们打印System.out.println(employee.getClass);得到的结果为cn.binyulan.domain.Employee._$$_jvst793_0,名字很奇怪吧,这个对象是Hibernate帮我们生成的,从名字可以看出它是对Employee类的增强类的对象,其实这就是个代理对象,这个对象里并没有我们需要的Employee的数据,所以如果你在session关闭后在使用employee来获取信息,如除了获得ID以外的employee.getName();就会出现如下异常:org.hibernate.LazyInitializationException: could not initialize proxy - no Session,这就说明了employee中没有我们需要的数据了。

 

      emp对象现在到底是什么呢,它其实是一个代理类,这个类具有查询数据库的能力,当session没有关闭的时候如果我们调用emp.getName等方法;那么这个类会去查询数据库并返回相应的数据。之后我们关闭session之后再去使用这个类就不会有异常了,可是我们如果调用emp.getName()只是为了让代理类去查数据库,如果别人看我们的代码时候觉得这两句在逻辑上根本就没有用,别人就很容易注释掉,一注释掉就又会出现异常了,所以hibernate提供了一个方法Hibernate.initialize(emp);这样就可以初始化这个代理对象了。

       不知道大家注意到没有,上面的那句代码Employee emp = (Employee)session.load(Employee.class,1)把emp强制转化为Employee类型,有人会问:不是返回的是代理对象么,那怎么又强制转换成Employee了呢,其实代理类是Employee的子类,它具有了比父类更强的能力(数据库查询),这个类是怎么生成的呢?其实hibernate使用了asm.jar和cglig-2.1.3.jar,在内存中修改Employee类的字节码,修改后的字节码只要符合class文件的规则,就可以创建出代理对象。

       Domain对象不应该final的,大家现在应该明白为什么了吧,如果是final的,那么就不可以继承,当然也就不可以产生代理对象,也就不能实现懒加载了,如果你不用懒加载,那么把domain对象设计成fianl的也是可以的。


0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 手机移动4g网卡怎么办 华为手机摄像头进灰怎么办 美图t8忘记密码怎么办 华为mate7忘记开机密码怎么办 华为mate9开机密码忘记怎么办 华为手机系统更新失败怎么办 mate9系统升级后耗电快怎么办 华为荣耀手机耗电快怎么办 荣耀10手机拍照不清晰怎么办 荣耀6x拍照模糊怎么办 华为荣耀P9进水了怎么办 苹果5s手机信号不好怎么办 苹果5s信号不好怎么办? 苹果5s像素不好怎么办 华为mate边缘有缝怎么办 华为mate8边缘有缝怎么办 手机系统占用运行内存大怎么办 安卓手机储存空间不足怎么办 手机显示系统空间不足怎么办 联系人存储已停止运行怎么办 荣耀note8听筒声音小怎么办 红米4x内存不足怎么办 安卓电视内存小怎么办 红米手机运行内存不足怎么办 红米手机存储空间不足怎么办 华为手机储存空间不足怎么办 大麦机顶盒遥控器丢了怎么办 大麦盒子总自动加软件怎么办 小米手机玩王者荣耀卡怎么办 荣耀8青春版信号差怎么办 华为mate8电池不耐用怎么办 华为4x内存小怎么办 发现手机被用过怎么办 华为p8手机声音小怎么办 手机指纹解锁密码忘了怎么办 华为p10黑色掉漆怎么办 金立手机导航信号弱怎么办 手机导航时gps信号弱怎么办 三星手机导航gps信号弱怎么办 小米5导航信号弱怎么办 华为手机导航gps信号弱怎么办