Hibernate的加载方式——GET与LOAD的对比

来源:互联网 发布:tsp 组合优化问题 编辑:程序博客网 时间:2024/06/05 17:19
区别

       从返回的结果上来看,get、load在检索到数据的时候,会返回对象(代理对象或实体对象),但他们的检索方式不同,这个后续在细说。get检索不到数据的时候,会返回null;而load检索不到数据会返回org.hibernate.ObjectNotFoundException。下面通过两个例子来分析一下get与load的工作原理。


工作原理

Get加载(数据库中存在检索的数据),这里只分析测试类,实体类就不再讨论了。

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. <SPAN style="FONT-FAMILY: Microsoft YaHei; FONT-SIZE: 18px">/** 
  2.  * 查询数据库中有数据的字段 
  3.  */  
  4. public void testGetNotNull() {  
  5.     Session session = null;  
  6.     try {  
  7.         session = HibernateUtils.getSession();  
  8.         session.beginTransaction();  
  9.         // 数据库中存在id为2的数据   
  10.         <SPAN style="COLOR: #ff0000">User user = (User)session.get(User.class2);</SPAN>  
  11.         System.out.println("---------Get加载--------");  
  12.         System.out.println(user);  
  13.         System.out.println(user.getId() + "---->>" + user.getName());  
  14.         System.out.println("------------------------");  
  15.         session.getTransaction().commit();  
  16.     } catch (Exception e) {  
  17.         e.printStackTrace();  
  18.         session.getTransaction().rollback();  
  19.     } finally {  
  20.         HibernateUtils.closeSession(session);  
  21.     }  
  22. }</SPAN>  


       因为Hibernate规定get方法不能使用延迟加载,当执行到User user = (User)session.get(User.class, 2);这条语句时,get方法首先会查询session缓存,没有的话就查询二级缓存,最后会查询数据库,因此在执行该语句的时候,会先发出sql语句进行查询。而且,执行get方法的时候,get方法每次都会从数据库直接查询。由于这是数据库中存在id为2的数据,因此,user会返回实体对象。如下图:



Get加载(数据库中不存在检索的数据)

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. <SPAN style="FONT-FAMILY: Microsoft YaHei; FONT-SIZE: 18px">/** 
  2.  * 查询数据库中不存在的数据 
  3.  */  
  4. public void testGetWithNull() {  
  5.     Session session = null;  
  6.     try {  
  7.         session = HibernateUtils.getSession();  
  8.         session.beginTransaction();  
  9.         // 数据库中不存在id为0的数据   
  10.         <SPAN style="COLOR: #ff0000">User user = (User)session.get(User.class0);</SPAN>  
  11.         System.out.println("---------Get加载--------");  
  12.         System.out.println(user);  
  13.         //System.out.println(user.getId() + "---->>" + user.getName());  
  14.         System.out.println("------------------------");  
  15.         session.getTransaction().commit();  
  16.     } catch (Exception e) {  
  17.         e.printStackTrace();  
  18.         session.getTransaction().rollback();  
  19.     } finally {  
  20.         HibernateUtils.closeSession(session);  
  21.     }  
  22. }</SPAN>  


      同上,在执行到User user = (User)session.get(User.class, 0);这条语句时,get方法每次都是直接查询数据库,在执行该语句时,Hibernate会发出sql语句,到数据库进行查询数据,由于id为0的数据不存在,get方法查询不到数据时,会返回null。因此,user的结果自然也是null了。如下图:




Load加载(数据库中存在检索的数据)

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. <SPAN style="FONT-FAMILY: Microsoft YaHei; FONT-SIZE: 18px">/** 
  2.  * 数据库中存在查询的数据 
  3.  */  
  4. public void testLoadNotNull() {  
  5.     Session session = null;  
  6.     try {  
  7.         session = HibernateUtils.getSession();  
  8.         session.beginTransaction();  
  9.         // 数据库中存在id为2的数据   
  10.         <SPAN style="COLOR: #ff0000">User user = (User)session.load(User.class2);</SPAN>  
  11.         System.out.println("----------Load加载-----------");  
  12.         System.out.println(user);  
  13.         System.out.println(user.getId() + "---->>" + user.getName());  
  14.         System.out.println("-----------------------------");  
  15.         session.getTransaction().commit();  
  16.     } catch (Exception e) {  
  17.         e.printStackTrace();  
  18.         session.getTransaction().rollback();  
  19.     } finally {  
  20.         HibernateUtils.closeSession(session);  
  21.     }  
  22. }</SPAN>  

    Hibernate中,load方法是支持延迟加载的,在执行到User user = (User)session.load(User.class, 2);这条语句时,load方法首先会查找session的persistent Context中是否存在缓存,如果存在则直接返回;如果没有缓存,则load方法会判断是否是lazy加载,如果不是lazy方式,则直接访问数据库,查询Id为2的数据,由于数据库中存在Id为2的数据,因此get方法会返回实体对象。

 如果load方法判断的是lazy方式加载,那么就需要建立代理对象,对象的initialized属性为false,target属性为null,在访问获得的代理对象的属性时,会访问数据库,找到记录后就会把该记录的对象复制到代理对象的target上,并将initialized属性设为true。在这个例子中,load方法采用的是lazy方式,因此在执行load方法时,Hibernate不会发出sql语句,因为此时Hibernate建立了代理对象,但并没有访问代理对象的属性。当执行System.out.println(user);时,Hibernate才会初次发出sql语句,去查询数据库。如下图:



Load加载(数据库中不存在检索的数据)

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. <SPAN style="FONT-FAMILY: Microsoft YaHei; FONT-SIZE: 18px">/** 
  2.  * 数据库中不存在查询的数据 
  3.  */  
  4. public void testLoadWithNull() {  
  5.     Session session = null;  
  6.     try {  
  7.         session = HibernateUtils.getSession();  
  8.         session.beginTransaction();  
  9.         // 数据库中不存在id为0的数据   
  10.         <SPAN style="COLOR: #ff0000">User user = (User)session.load(User.class0);</SPAN>  
  11.         System.out.println("----------Load加载-----------");  
  12.         System.out.println(user);  
  13.         //System.out.println(user.getId() + "---->>" + user.getName());  
  14.         System.out.println("-----------------------------");  
  15.         session.getTransaction().commit();  
  16.     } catch (Exception e) {  
  17.         e.printStackTrace();  
  18.         session.getTransaction().rollback();  
  19.     } finally {  
  20.         HibernateUtils.closeSession(session);  
  21.     }  
  22. }</SPAN>  

    同上,在执行到load方法时,load方法会首先查询session中是否存在缓存,如果存在则直接返回,如果不存在则会判断是否为lazy,这里设置的是lazy方式,因此load方法会认为数据库中存在数据,直接建立代理对象,把代理对象返回给user。

    而执行到System.out.println(user);时,Hibernate会发出sql语句,访问数据库查询Id为0的数据,由于数据库中不存在Id为0的数据,因此load方法会返回org.hibernate.ObjectNotFoundException,直接抛出异常。如下图:
<DIV style="TEXT-ALIGN: center
0 0