hibernate的一级缓存

简介:
       Hibernate的一级缓存其实就是Session内置的一个Map,用来缓存它操作过的实体对象,对象的主关键字ID是Map的key,实体对象就是对应的值。所以,一级缓存是以实体对象为单位进行存储的,访问时也是以实体为单位的(直接访问属性是不能使用缓存的),并且要求使用主关键字ID来进行访问。
       
       一级缓存是由Session提供的,所以它只存在于Session的生命周期中,当程序调用save(),update(),saveorupdate()等方法以及调用查询接口list,filter,iterate时,如果session缓存中还不存在相应的对象,Hibernate会把该对象加入到一级缓存中,当Session关闭的时候该Session所管理的一级缓存也会立即被清除。当程序调用get(),load(),iterate(查询实体对象才支持一级缓存,查询普通属性则不支持一级缓存)时,Hibernate会先到缓存中去拿,如果缓存中已经存在目标对象,则直接拿来而不再查询数据库,否则,必须发出查询语句到数据库中查。
 
       对于一级缓存的使用,其实大多都是由Hibernate自动维护的,我们能做的是很少的,既不能卸载它,也不能对它进行任何的配置。但是,好在Hibernate给我们提供了两个方法可以对它进行简单的管理:session.clear(),session.evict() 。前者是清空一级缓存中所有的对象,后者是把某一个对象从一级缓存中清除。项目中,当需要进行大批量数据一次性更新时,在不知不觉中hibernate会占用大量内存,这时就应该阶段性地调用clear()方法来清空一级缓存中的对象,控制一级缓存的大小,以避免产生内存溢出的情况。
 
        如果数据量特别大,我们一般考虑采用jdbc实现,因为它不用把大批量的数据事先加载到内存中,然后再进行更新与修改。所以不会消耗大量内存。如果jdbc也不能满足要求可以考虑采用数据本身的特定导入工具等其它办法。
1.实体类:Student.java
public  class Student { 
   private Integer id; 
   private String name; 
   //一系列的setter.getter方法 
}

2.映射文件:
  Student.hbm.xml
   < class  name ="com.sxt.hibernate.cache.entity.Student"  table ="sxt_hibernate_student" > 
     < id  name ="id"  length ="4" > 
       < generator  class ="native" > </ generator > 
     </ id > 
     < property  name ="name"  length ="10" > </ property > 
   </ class >
 
3.Hibernate配置文件
  省略。
 
4.  测试方法:
   public  static  void main(String[] args) { 
    Session session =  null
    Transaction t =  null
     try { 
      session = HibernateUtils.getSession(); 
      t = session.beginTransaction(); 
       /** 
        * 在同一个session中发出两次load查询 
        */
 
/*      //如果前面没有用session操作过此student对象,在这里会发出sql语句. 
      Student student = (Student)session.load(Student.class, 1); 
      System.out.println("student.name=" + student.getName()); 
        
      //不会发出sql,因为load使用一级缓存 
      student = (Student)session.load(Student.class, 1); 
      System.out.println("student.name=" + student.getName());*/
 
        
       /** 
        * 在同一个session中发出两次get查询 
        */
 
/*      Student student = (Student)session.get(Student.class, 1); 
      System.out.println("student.name=" + student.getName()); 
        
      //不会发出sql,因为get也使用一级缓存 
      student = (Student)session.get(Student.class, 1); 
      System.out.println("student.name=" + student.getName());*/
 
        
       /** 
        * 在同一个session中发出两次iterate查询实体对象 
        */
 
/*      Student student = (Student)session.createQuery("from Student s where s.id=1").iterate().next(); 
      System.out.println("student.name=" + student.getName()); 
        
      //会发出查询id的sql,不会发出查询实体对象的sql,因为iterate在查询实体对象时也使用缓存 
      student = (Student)session.createQuery("from Student s where s.id=1").iterate().next(); 
      System.out.println("student.name=" + student.getName());*/
 
        
       /** 
        * 在同一个session中发出两次iterate查询实体对象 
        */
 
/*      //发出sql直接插name,不再插id 
      //select student0_.name as col_0_0_ from sxt_hibernate_student student0_ where student0_.id=1 
      String name = (String)session.createQuery("select s.name from Student s where s.id=1").iterate().next(); 
      System.out.println("student.name=" + name); 
        
      //iterate查询普通属性,一级缓存不会缓存,所以发出sql 
      //由此可见,一级缓存是缓存实体对象的 
      name = (String)session.createQuery("select s.name from Student s where s.id=1").iterate().next(); 
      System.out.println("student.name=" + name);*/
 
        
       /** 
        * 在同一个session中先save,在发出load查询save过的数据 
        */
 
/*      Student stu = new Student(); 
      stu.setName("吴奇隆"); 
        
      Serializable id = session.save(stu);//主键生成方式采用native,是个序列化的id. 
        
      //不会发出sql,因为save是使用缓存的.save之后,会把对象放到一级缓存中. 
      //再load时,直接到一级缓存中去拿就可以了. 
      Student student = (Student)session.load(Student.class, id); 
      System.out.println("student.name=" + student.getName());*/
 
        
       /** 
        * 向数据库中批量加入5000条数据 
        */
 
/*      for (int i=0; i<5000; i++) { 
        Student student = new Student(); 
        student.setName("stu_" + i); 
        session.save(student); 
        //每20条数据就强制session将数据持久化 
        //同时清除缓存,避免大量数据造成内存溢出 
        if ( i % 30 == 0) { 
          session.flush(); 
          session.clear(); 
        } 
      }*/
 
        
       /** 
        * 在数据库中一次性更新大批量数据 
        */
 
/*      Iterator<Student> students=session.createQuery("from Student s where s.id>100").iterate(); 
      while(students.hasNext()){ 
        Student stu =(Student)students.next(); 
        stu.setName("n_"+stu.getName()); 
        //将本批插入的对象立即写入数据库并释放内存 
        session.flush(); 
        session.clear(); 
      }*/
 

       /** 
        * Hibernate并不适合处理大批量的数据,通常我们都跳过Hibernate API,而直接采用JDBC API来做. 
        */
 
/*      Connection conn =session.connection(); 
      PreparedStatement    pstmt = conn.prepareStatement("update sxt_hibernate_student set name='s'||substr(name,4,8) "+"where id >100"); 
      pstmt.executeUpdate();*/
 
        
       /** 
        * 其实批处理大量数据更新最好的解决方法就是用创建存储过程,直接利用底层数据库.这样性能最好. 
        */
 
       /* 
        *create or    replace procedure StudentUpdate(s_id in number) as    
             *begin 
                *update sxt_hibernate_student set name='n_'||name where id>s_id; 
                *end; 
        */
 
      Connection conn=session.connection(); 
                        String str= "{call StudentUpdate(?)}"
                        CallableStatement cstmt= conn.prepareCall(str); 
                        cstmt.setInt(1,100); 
                        cstmt.executeUpdate(); 

      t.commit(); 
    }  catch (Exception e) { 
      e.printStackTrace(); 
      t.rollback(); 
    }  finally { 
      HibernateUtils.closeSession(session); 
    } 
     /** 
     * 开启两个session中发出load查询 
     */
 
/*    try{ 
      session=HibernateUtils.getSession(); 
      t=session.beginTransaction(); 
      Student student = (Student)session.load(Student.class, 1); 
      System.out.println("student.name=" + student.getName()); 
    }catch(Exception e){ 
      e.printStackTrace(); 
      t.rollback(); 
    }finally{ 
      HibernateUtils.closeSession(session); 
    } 
    try{ 
      session=HibernateUtils.getSession(); 
      t=session.beginTransaction(); 
      //会发出查询语句,因为一级缓存时和session绑定的,每个session都有自己的一级缓存,不同session间不能共享一级缓存. 
      //上一个session已经关闭了,所以此处还要发出查询语句. 
      Student student = (Student)session.load(Student.class, 1); 
      System.out.println("student.name=" + student.getName()); 
    }catch(Exception e){ 
      e.printStackTrace(); 
      t.rollback(); 
    }finally{ 
      HibernateUtils.closeSession(session); 
    }*/
 
  }



     本文转自NightWolves 51CTO博客,原文链接: http://blog.51cto.com/yangfei520/278299 ,如需转载请自行联系原作者

相关文章
|
14天前
|
缓存 Java 数据库连接
hibernate二级缓存
在配置和使用Hibernate二级缓存时,你应该根据应用的需求和性能要求,合理选择缓存提供者和配置参数,以达到性能优化的目的。 买CN2云服务器,免备案服务器,高防服务器,就选蓝易云。百度搜索:蓝易云
16 1
|
9月前
|
存储 SQL 缓存
MyBatis一级缓存 二级缓存
MyBatis一级缓存 二级缓存
65 0
|
5月前
|
缓存 Java 数据库连接
Mybatis中一级缓存和二级缓存使用详解
Mybatis中一级缓存和二级缓存使用详解
65 0
|
7月前
|
缓存 Java 数据库连接
mybatis之一级缓存和二级缓存~
mybatis之一级缓存和二级缓存~
|
8月前
|
缓存 Java 数据库连接
MyBatis 的一级缓存和二级缓存
MyBatis 的一级缓存和二级缓存
154 0
|
9月前
|
存储 SQL 缓存
mybatis中一级缓存和二级缓存
mybatis中一级缓存和二级缓存
66 0
|
SQL 存储 缓存
hibernate的一级缓存
hibernate的一级缓存
88 1
hibernate的一级缓存
|
SQL 存储 缓存
Hibernate 一二级缓存
Hibernate 一二级缓存
Hibernate 一二级缓存
|
存储 SQL 缓存
【Mybatis】(四)一级缓存和二级缓存
【Mybatis】(四)一级缓存和二级缓存
165 0
|
SQL 缓存 JavaScript
Hibernate的一级缓存
缓存将数据库/硬盘上文件中数据,放入到缓存中(就是内存中一块空间).当再次使用的使用,可以直接从内存中获取.
99 0
Hibernate的一级缓存