【Hibernate七】session的缓存机制

看一个测试:
      @Test
      public  void testGet(){
          Session session  =  sessionFactory.openSession();
          Classes classes = (Classes)session.get(Classes. class  , 1L);//会发出查询语句
          classes = (Classes)session.get(Classes.  class, 1L);//不会发出查询语句,有缓存!
          session.close();
     }

以上代码表明了session具有某种缓存机制!

session的缓存
   1、生命周期
       当session创建的时候,session的缓存就存在了,当执行session.close方法时,sesison关闭,缓存清空
   2、缓存的性质
       session缓存中存放私有数据,因为session从threadlocal中产生,所以session中的数据是线程安全的
   3、操作
        (1).数据库中的数据怎么样加载到缓存中
           利用session.get,load,save,update,getStudents都可以把相应的数据放入到session的缓存中
            根据student加载classes?

        (2)应用程序在什么时候读取到缓存中的数据
           利用session.get,load,getStudents(一的一端加载多的一段的集合)都可以读取到session缓存中的数据

        (3)缓存中的数据怎么样进行清空
           session.clear
              清空缓存   把一个持久化状态变成脱管状态;对象在缓存中,那么对象就处于持久化状态;

        (4)怎么样进行清空一个对象(来自于缓存)
           session.evict

        (5)如果缓存中的数据和数据库中的数据不同步的情况下,怎么样把缓存中的数据同步到数据库中
           session.flush(),发出sql语句!不会清空缓存!
              1、检查 session缓存中所有的持久化对象
                  ①、如果该对象在数据库中有相应的记录,则查看快照区
                       如果一样,则什么都不做
                       如果不一样,则发出update语句
                  ②、如果该对象在数据库中没有相应的记录,则进行insert操作
              2、检查对象与对象之间的级联操作cascade="save-update","all"
              3、检查关系操作  inverse="false"(维护关系),"true"(不维护)

        (6)如何把数据库中的数据刷到缓存中
              session.refresh方法
        (7) 插入大量的数据时,批量操作
             session.flush();
             session.clear();

总结:
对象处于缓存中,那么对象就处于持久化状态;将对象从缓存中移除,对象就不在处于持久化状态!
对象是否处于持久化状态,与其是否在缓存中是息息相关的!

测试代码:
public  class SessionCacheTest extends HibernateUtils{
      /**
      * 测试get方法的缓存情况!
      */
      @Test
      public  void testGet(){
          Session session  =  sessionFactory.openSession();
          Classes classes = (Classes)session.get(Classes. class  , 1L);//会发出查询语句
          classes = (Classes)session.get(Classes.  class, 1L);//不会发出查询语句,有缓存!
          session.close();
     }
      /**
      * <set name="students" cascade="save-update"
      *        inverse="false" lazy="extra" fetch="select" >
      * 测试load(),懒加载时的情况
      */
      @Test
      public  void testLoad(){
          Session session  =  sessionFactory.openSession();
          Classes classes = (Classes)session.load(Classes. class  , 1L);//懒加载,不会发出 sql语句
          classes.getCname();  //发出sql语句
          classes = (Classes)session.load(Classes.  class, 1L);//不发出sql语句
          classes.getCname();
          session.close();
     }
      /**
      * 插入一个对象时,先保存到缓存中;
      */
      @Test
      public  void testSave(){
          Session session  =  sessionFactory.openSession();
          Transaction transaction = session.beginTransaction();
          
          Classes classes =  new Classes();
          classes.setCname(  "e45");
          session.save(classes);  //cid 会自动的生成
          
          classes = (Classes)session.get(Classes.  class, classes.getCid());//不会发出 sql语句,从缓存中获取
          
          transaction.commit();
          session.close();
     }
      /**
      * 更新对象时,同样先保存到缓存中,然后才同步到数据库中;
      */
      @Test
      public  void testUpdate(){
          Session session  =  sessionFactory.openSession();
          Transaction transaction = session.beginTransaction();
          
          Classes classes  = (Classes)session.get(Classes. class  , 1L);
          
          session.evict(classes);  //把一个对象从持久化状态变为托管状态,即从缓存中移除数据

          session.update(classes);  //将数据重新加载到缓存,尽管没有改变属性,但是在commit时仍然会发出update语句
          
          classes  = (Classes)session.get(Classes.  class, 1L);//数据已在缓存中,不会发出 sql语句
          
          transaction.commit();
          session.close();
     }
      @Test
      public  void testUpdate2(){
          Session session  =  sessionFactory.openSession();
          Transaction transaction = session.beginTransaction();
          
          Classes classes  = (Classes)session.get(Classes. class  , 1L);
          
          session.evict(classes);  //把一个对象从持久化状态变为托管状态,即从缓存中移除数据
          
          classes  = (Classes)session.get(Classes.  class, 1L);//会发出查询的 sql语句,重新将数据加载到缓存中;
          
          session.update(classes);  //属性没改变,不会发出update语句
          
          transaction.commit();
          session.close();
     }
      /**
      * 测试一对多,从一的一端获取集合;
      */
      @Test
      public  void testSet(){
          Session session  =  sessionFactory.openSession();
          Transaction transaction = session.beginTransaction();
          Classes classes  = (Classes)session.get(Classes. class  , 1L);
          
          Set<Student> students = classes.getStudents(); //不会发出 sql语句,因为懒加载
            for(Student student :students){//遍历集合的时候,才发出 sql语句
              System.  out.println(student.getSname());
          }
          
          students = classes.getStudents();
            for(Student student :students){//数据已在缓存中,不会发出 sql语句
              System.  out.println(student.getSname());
          }
          transaction.commit();
          session.close();
     }
      /**
      * flush方法,将缓存中的数据同步到数据库中;会更新缓存,不会清除缓存!
      */
      @Test
      public  void testSession_Flush(){
          Session session  =  sessionFactory.openSession();
          Transaction transaction = session.beginTransaction();
          
          Classes classes  = (Classes)session.get(Classes. class  , 1L);
          Set<Student> students = classes.getStudents();
            for(Student student :students){
              student.setDescription(  "a6");
          }
          session.flush();  //发出update或者insert语句,会更新缓存,不会清空缓存
          
          classes  = (Classes)session.get(Classes.  class, 1L);//不发出sql语句
          students=classes.getStudents();
            for(Student student :students){
               System.  out.println(student.getDescription());//不发出 sql语句,得到的是更新后的缓存的数据;
          }
          transaction.commit();
          session.close();
     }
     
      /**
      * 向classes表中插入100000条数据
      * 由于插入数据是先将数据保存到缓存中,数据量太大时,内存会溢出!
      * 故缓存中的数量达到一定数目的时候,需要flush,执行插入操作,然后clear,清空缓存
      */
      @Test
      public  void testInsertBatch(){
          Session session  =  sessionFactory.openSession();
          Transaction transaction = session.beginTransaction();
            for(int i=0;i<10000;i++){//
              Classes classes =  new Classes();
              classes.setCname(  "asdf"+i);
              session.save(classes);
                if(i%50==0){//定时把 sql语句刷到数据库中,并且清空缓存中的数据
                   session.flush();
                   session.clear();
              }
          }
          transaction.commit();
          session.close();
     }
     
      /**
      * 把数据库中的数据同步到缓存中
      */
      @Test
      public  void testRefresh(){
          Session session  =  sessionFactory.openSession();
          Transaction transaction = session.beginTransaction();
          
          Classes classes = (Classes)session.get(Classes. class  , 1L);
          classes.setDescription(  "asfads");
          
          session. refresh(classes); //把数据库中的数据重刷到指定的对象中
          
          System.  out.println(classes.getDescription());//得到的是数据库中的数据
          
          transaction.commit();
          session.close();
     }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值