• Hibernate之list和iterator


    在Hibernate3中将Session.find(),Session.iterator()换成:session.createQuery().list(),session.createQuery().iterator(),(实现机制并没有什么区别);

    两者都是根据指定条件查询并返回符合查询的条件的实体对象;

    看下session.createQuery().list():

    Java代码
    1. List<TUser> users = session.createQuery(hql).list();   
    2. int len = users.size();   
    3. for (int i = 0; i < len; i++) {   
    4.     TUser user = users.get(i);   
    5.     System.out.println("User name:"+user.getName());   
    6. }  

    在控制台上只会输出:

    Sql代码
    1. Hibernate: select   tuser0_.userid as userid0_, tuser0_.name as name0_,tuser0_.age as age0_, tuser0_.info as info0_  from t_user tuser0_  where   tuser0_.age>316    

    显示的结果为:

    Java代码
    1. User name:keith 299  

     

    在看下session.createQuery().iterate():

    Java代码
    1. Iterator it = session.createQuery(hql).iterate();   
    2. while (it.hasNext()) {   
    3.     TUser users = (TUser) it.next();   
    4.     System.out.println("user Name:"+users.getName());   
    5. }  

     看下控制台上的输出:

    Sql代码
    1. Hibernate: select   tuser0_.userid as col_0_0_  from  t_user tuser0_ where   tuser0_.age>316   
    2. Hibernate: select   tuser0_.userid as userid0_0_,tuser0_.name as name0_0_, tuser0_.age as age0_0_,tuser0_.info as info0_0_   from    t_user tuser0_  where   tuser0_.userid=?  

     所显示的结果为:

    Java代码
    1. user Name:keith 299  

     

    两者相比较,list()只发一条语句将符合条件的数据全部查出,而iterator()却现将id查出来,然后根据id再将符合条件的数据查出,这就构成了N+1的问题;既然list更高效,为什么hibernate还将iterator存在呢?

     

    这个问题与Hibernate缓存机制密切相关,我们将两种方法写在一起:

    Java代码
    1. List<TUser> users = session.createQuery(hql).list();   
    2. int len = users.size();   
    3. for (int i = 0; i < len; i++) {   
    4.     TUser user = users.get(i);   
    5.     System.out.println("user Name:"+user.getName());   
    6. }   
    7.   
    8. System.out.println("  query by list is Over,and query by iterator is start...");   
    9.   
    10. Iterator it = session.createQuery(hql).iterate();   
    11.   
    12. while (it.hasNext()) {   
    13.     TUser user = (TUser) it.next();   
    14.     System.out.println("users name:"+user.getName());   
    15. }  

     看下控制台的输出:

    Sql代码
    1. Hibernate: select  tuser0_.userid as userid0_,tuser0_.name as name0_,tuser0_.age as age0_,tuser0_.info as info0_   from   t_user tuser0_   where   tuser0_.age>316   
    2.   
    3. user Name:keith 299   
    4.   
    5.  query by list is Over,and query by iterator is start...   
    6.   
    7. Hibernate: select  tuser0_.userid as col_0_0_  from  t_user tuser0_ where  tuser0_.age>316   
    8.   
    9. users name:keith 299  

     只是将之前的list()和iterator()放在一起使用,这时的iterator只执行了一条SQL;其中的差异在于hibernate的缓存机制;

    list()方法将执行Select SQL从数据库中获取所有符合满足条件的记录并构造相应的实体对象,实体对象构建完毕后,就将其纳入缓存;

    这样等到iterator()执行时,首先会执行一条SQL来查询符合条件数据的id,随即,iterator方法首先在本地缓存内根据id查找对应的实体对象是否存在,如果缓存中已经存在对应的数据,则直接以此数据对象作为查询结果;如果没有找到,则再次执行Select语句获得对应数据库中的表记录(如果iterator在数据库中查到并构建了完整的数据对象,也会将其纳入缓存中);

    在上面这个实例中,list()将读取的数据放入缓存中,iterator()直接可以用于是出现了以上的结果;

     

    当我们再次执行上面的程序,发现结果还是一样的;list()并没有去读取它自己放进缓存的数据,因为当我们list()查询完后,即使缓存中有一些符合条件的数据,但是我们也无法保证这些数据就是合法的,如果更改下条件,将大于316改成300;那么缓存中的数据只满足大于316不会满足大于300;所有list()方法还是需要执行一次Select SQL来保证结果的完整性;得出结论:list()实际上无法利用缓存,它对缓存只写不读,而iterator()可以充分利用缓存,如果目标数据只读或者读取相当频繁,可以使用iterator()来减少性能上的消耗;

     

    但是会出现这样一个问题,如果是海量数据怎么办?如果超过10万条记录的话,会有很大的可能出发OutOfMemoryError;导致系统异常;那么就用iterator()和evict()来解决吧!将内存消耗保持在可以接受的范围内;比如:

    Java代码
    1. Iterator it = session.createQuery(hql).iterate();   
    2. while (it.hasNext()) {   
    3.     TUser users = (TUser) it.next();   
    4.     //在一级缓存中清理   
    5.     session.evict(users);   
    6.     //在二级缓存中清理,二级缓存可以设定   
    7.     SessionFactory.evict(TUser.class, users.getUserid());   
    8.     System.out.println("user Name:"+users.getName());   
    9. }  

     但是这样的话,由于JVM的异步内存回收机制,无效对象会不断的在内存中积累等待回收,如果数据量很大,必然会频繁的激发JVM的内存回收机制,导致系统性能急剧下降。因此对于这样的问题,最好使用SQL或者存储过程!

  • 相关阅读:
    全代码实现ios-4
    集训第一次周赛题目及题解
    网站登录时密码忘记,通过向邮箱发送验证链接实现重置密码的实现方法
    hdu 1861-游船出租
    c#获取或修改配置文件
    今天做php经典实例,发现,我是对的,面试官给我说错了
    HDU 4637 Rain on your Fat brother 线段与半圆和线段交 简单题
    Qt之图标切分与合并
    标准容器的共性及举例
    如何提高数据库update更新的速度
  • 原文地址:https://www.cnblogs.com/iamconan/p/7383624.html
Copyright © 2020-2023  润新知