• Hibernate一级缓存和三种状态


      Hibernate一级缓存又称session缓存,生命周期很短,跟session生命周期相同。

      三种状态:1.transient(瞬时态):刚new出来的对象,既不在数据库中,也不在session管理内.

           2.persistent(持久化状态):在session缓存中,在数据库中可能有记录(注意)。如果一个对象时瞬时态,调用save会变成持久态,但是如果不提交事务的话,数据库是 不会有这条记录的。

           3.detached(离线状态):即对象存在于数据库中,但没有被session所管理。 

      三种状态可以相互转换:

            1.瞬时对象(通过new关键字获取):

               瞬时---持久:save或者saveOrUpdate

               瞬时---脱管:setId()

      2.持久化对象(通过get/load或Query查询获取):

           持久---瞬时态:delete(),删除持久化对象,不建议再次使用到同一个对象。  

      持久---离线态:evict()删除session缓存中某个对象,close()清楚session缓存,clear()清除session缓存中所有对象。

      3.脱管对象(无法直接获得):

         脱管---瞬时:setId(null),删除对象OID

         脱管---持久:save或saveOrUpdate或lock

           果对象已经是持久化状态,那么不管对对象做过多次修改,或者操作多次save()或update()方法,都不会发送sql语句。只有在事务提交时,当且仅当当前对象(快照区的对象)与session缓存中的对象不一致时,才会发送update语句。

      对于瞬时态对象,调用save方法变为持久化状态,发送insert语句。

      对于离线状态,调用update方法变为持久化状态,发送select语句。

           一级缓存:

           又称session缓存,同session生命周期一样,都很短,属于事务隔离级别。

           Hibernate缓存是通过集合实现的,Hibernate封装了map和list集合。Hibernate向一级缓存中存放数据时,同时会保存一份快照数据。当执行flush()时,会比较一级缓存与快照中

    的数据,如果不一致,会执行更新。

      用处:当要查询的对象在session缓存中已经存在时,将不会再向数据库发送sql语句,而是直接从session缓存中获取对象。

      session.get()、session.load()支持一级缓存,createQuery()不支持一级缓存。即即使是两次相同的查询,获得list也是相同的,也会向数据库发起两次查询,iterate支持一级缓存。

            get():

             session=HibernateUtil.getSession();

       Transaction tr=session.beginTransaction();

      User user=session.get(User.class,1);

      User user1=session.get(User.class,1);

      tr.commit();

      session.close();

      控制台输出:

      

      总结:说明get是支持一级缓存的。使用get查询出的对象会放到一级缓存中,下次使用get查询对象时,如果对象已经存在一级缓存中,就直接从缓存中取对象,而不用再从

      数据库查对象。

            操作:

      1.flush():

      清出缓存,一个是手动调用flush(),还有就是调用commit()时也会清出缓存;将缓存清出后,就会向数据库发送sql语句。将缓存同步到数据库。首先会将缓存中的数据与快照数据进行比较,如果不一致,才会发出update语句。

           session=HibernateUtil.getSession();

      Transaction tr=session.beginTransaction();

      //此时会产生快照

      User user=session.get(User.class,1);

       //改变的是快照区的对象

        user.setName("XXX");

      //手动flush,因为快照区的对象与缓存中的对象有区别,此时会向数据库发送sql语句,但是数据库中的数据并没有发生改变,只有提交事务时,数据库中的数据才会改变。

      session.flush();

      tr.commit();

      session.close();

      2.refresh():

      将数据库的数据同步到缓存中,这个过程一定会产生更新语句,同步一级缓存和快照。

      session=HibernateUtil.getSession();

      Transaction tr=session.beginTransaction();

      User user=session.get(User.class,1);

      user.setName("XXX");

           //数据库中的数据同步到一级缓存和快照,向数据库发送一次查询语句

      session.refresh(user);

      System.out.println(user);

           //因为调用了refresh使数据库与一级缓存的对象同步,所以不会向数据库发送update语句。

      tr.commit();

      session.close();

      3.clear():

      清空所有对象的一级缓存,对对象的所有操作全部失效,恢复到原来快照的数据

      session=HibernateUtil.getSession();

      Transaction tr=session.beginTransaction();

      User user=session.get(User.class,1);

      user.setName("XXX");

      //调用clear清空了session缓存所有数据,数据库不会发生任何变化

      session.clear();

      tr.commit();

      session.close();

      4.evict():

      对指定的对象清除一级缓存

      session=HibernateUtil.getSession();

      Transaction tr=session.beginTransaction();

      User user1=session.get(User.class,1);

      User user2=session.get(User.class,2);

    //清除一级缓存中的user1的所有修改操作

      session.evict(user1);

    //调用get获取id为1的user时还会向数据库发送sql语句

      User user11=session.get(User.class,1);

      User user22=session.get(User.class,2);

      tr.commit();

      session.close();

     

    总结:因为对user1调用了evict()方法,user1在一级缓存中被清除,所以再次get()id为1的对象时,在缓存中没有该对象,会向数据库再次发送sql语句。

  • 相关阅读:
    采样频率和采样点数以及奈奎斯特采样定理
    三阶截断点TOI或IP3
    动态库、静态库
    Qt添加静态库
    给测试开发工程师的5条建议
    软件测试中7个令人震惊的真相
    2022 年值得测试同学关注的技术趋势
    度量自动化测试效果的10个指标
    如何优化selenium webdriver的执行速度
    单元测试用例该如何设计
  • 原文地址:https://www.cnblogs.com/fengshine/p/10174726.html
Copyright © 2020-2023  润新知