导航

Hibernate 一级缓存

Posted on 2017-10-09 11:13  耍流氓的兔兔  阅读(199)  评论(0编辑  收藏  举报

 

一级缓存:

  Hibernate的一级缓存是指Session(属于事务范围的缓存,由Hibernate管理,无需干预)

  它是一块内存空间,用来存放从数据库查询出的java对象,有了一级缓存,应用程序可以减少访问数据库的次数,提高了性能

  在使用Hibernate查询对象的时候,首先会使用对象属性的OID值(对应表中的主键)在Hibernate的一级缓存进行查找

    如果找到,则取出返回,不会再查询数据库

    如果没有找到,再到数据库中进行查询操作。然后将查询结果存放到Session一级缓存中

  Test:

        //第一次查询(会查询数据库)
        Customer c1 = session.get(Customer.class, 15);
        System.out.println(c1);
        
        //第二次查询(不会查询数据库)
        Customer c2 = session.get(Customer.class, 15);
        System.out.println(c2);
tx.commit(); session.close();

  Console:

Hibernate: 
    select
        customer0_.c_id as c_id1_0_0_,
        customer0_.c_name as c_name2_0_0_,
        customer0_.c_gender as c_gender3_0_0_,
        customer0_.c_age as c_age4_0_0_,
        customer0_.c_level as c_level5_0_0_ 
    from
        t_customer customer0_ 
    where
        customer0_.c_id=?
com.roxy.hibernate.pojo.Customer@31c269fd
com.roxy.hibernate.pojo.Customer@31c269fd

----- 只执行一次SQL语句

  Test2:测试一级缓存的范围

        //第一次查询(会查询数据库)
        Session session1 = HibernateUtil.openSession();
        Transaction tx1 = session1.beginTransaction();
         
        Customer c1 = session1.get(Customer.class, 15);
        System.out.println(c1);
        
        tx1.commit();
        session1.close();
        
        //第二次查询(会查询数据库)
        Session session2 = HibernateUtil.openSession();
        Transaction tx2 = session2.beginTransaction();
        
        Customer c2 = session2.get(Customer.class, 15);
        System.out.println(c2);
        
        tx2.commit();
        session2.close();

  Console:

Hibernate: 
    select
        customer0_.c_id as c_id1_0_0_,
        customer0_.c_name as c_name2_0_0_,
        customer0_.c_gender as c_gender3_0_0_,
        customer0_.c_age as c_age4_0_0_,
        customer0_.c_level as c_level5_0_0_ 
    from
        t_customer customer0_ 
    where
        customer0_.c_id=?
com.roxy.hibernate.pojo.Customer@31c269fd
Hibernate: 
    select
        customer0_.c_id as c_id1_0_0_,
        customer0_.c_name as c_name2_0_0_,
        customer0_.c_gender as c_gender3_0_0_,
        customer0_.c_age as c_age4_0_0_,
        customer0_.c_level as c_level5_0_0_ 
    from
        t_customer customer0_ 
    where
        customer0_.c_id=?
com.roxy.hibernate.pojo.Customer@4593ff34

----- 执行两次SQL查询,说明一级缓存的作用范围是session

快照机制:

    当执行commit()时,Hibernate同时会清理session的一级缓存(flush),也就是将堆内存中的数据与快照中的数据进行对比,如果不一致,会执行同步操作(update)操作,如果一致,则不执行update

  只有持久化对象能走快照机制

  快照是数据的副本

  快照属于一级缓存

  快照是在堆内存中的

  快照的作用:保证数据的一致性

   Test:

        Customer c1 = session.get(Customer.class, 15);
        c1.setName("harry");
        
        tx.commit();
        session.close();

  Console:

Hibernate: 
    select
        customer0_.c_id as c_id1_0_0_,
        customer0_.c_name as c_name2_0_0_,
        customer0_.c_gender as c_gender3_0_0_,
        customer0_.c_age as c_age4_0_0_,
        customer0_.c_level as c_level5_0_0_ 
    from
        t_customer customer0_ 
    where
        customer0_.c_id=?
Hibernate: 
    update
        t_customer 
    set
        c_name=?,
        c_gender=?,
        c_age=?,
        c_level=? 
    where
        c_id=?

----- 自动执行update方法

一级缓存管理:

   如果对象不在一级缓存中,无法进行对比,数据库不能自动更新

  一级缓存默认开启,无法关闭,只能清空(evict | clear | close),持久态转化为游离态

    evict:清除一级缓存中某个对象

    clear:清除一级缓存所有对象

       close:关闭Session,清除一级缓存

  Test:

        Session session = HibernateUtil.openSession();
        Transaction tx = session.beginTransaction();
        
        //查询
        Customer c1 = session.get(Customer.class, 16);
        c1.setName("draco");
        
        //session.evict(c1);
        session.clear();
                
        tx.commit();
        session.close();

  Console:

    select
        customer0_.c_id as c_id1_0_0_,
        customer0_.c_name as c_name2_0_0_,
        customer0_.c_gender as c_gender3_0_0_,
        customer0_.c_age as c_age4_0_0_,
        customer0_.c_level as c_level5_0_0_ 
    from
        t_customer customer0_ 
    where
        customer0_.c_id=?

----- 只执行select,没有自动更新

   其他操作:

    flush:

      修改一级缓存,针对内存操作,在session执行flush操作时,将缓存变化同布在数据库

    refresh:

      重新查询数据库,更新快照和一级缓存

 Session手动控制缓存:

  Always:每次查询时,session都会flush,即自动更新

  Auto:在某些查询时,session会默认flush,例如commit

  Commit:在事务提交时

  Manual:只有手动提交事务才会同步到数据库

  参考链接:http://blog.csdn.net/luckyzhoustar/article/details/47665495