Hibernate一级缓存

一、一级缓存

一级缓存也称为session缓存,默认总是开启的,生命周期与session相同,使用一级缓存可以减少与数据库的交互,提高数据库访问性能;一级缓存只能作用于当前session,其他的session无法使用。

二、原理

一级缓存采用的是Key-Value的MAP方式来实现的。在缓存实体对象时,对象的主关键字ID是MAP的Key,实体对象就是对象的值。所以说一级缓存是以实体对象为单位进行存储的。访问的时候使用的是主键关键字ID。一级缓存使用的是自动维护的功能。但可以通过session提供的手动方法对一级缓存的管理进行手动干预。
evict:用于将某个对象从Session的一级缓存中清除。
clear:用于将一级缓存中的所有对象清除。

*以下测试针对各种方法对一级缓存的存取情况

get方式支持一级缓存

@Test
public void testLoad(){
    Session session = null;
    Transaction tran = null;
    try{
        session = SessionUtil.getSession();
        tran = session.beginTransaction();
        TBook book = (TBook)session.load(TBook.class,1);
        System.out.println("图书名称:"+book.getBName());

        book = (TBook)session.get(TBook.class,1);
        System.out.println("图书名称:"+book.getBName());

        tran.commit();

    }catch(Exception e){
        e.printStackTrace();
    }
    finally{
        SessionUtil.close(session);
    }
}

结果:

Hibernate: 
    select
        tbook0_.id as id1_0_0_,
        tbook0_.author as author2_0_0_,
        tbook0_.b_name as b_name3_0_0_,
        tbook0_.b_price as b_price4_0_0_,
        tbook0_.pubDate as pubDate5_0_0_ 
    from
        admindb.t_book tbook0_ 
    where
        tbook0_.id=?
图书名称:红楼梦
图书名称:红楼梦
book1 == book2 ? :true

load方式支持一级缓存

@Test
public void testLoad(){
    Session session = null;
    Transaction tran = null;
    try{
        session = SessionUtil.getSession();
        tran = session.beginTransaction();
        TBook book1 = (TBook)session.load(TBook.class,1);
        System.out.println("图书名称:"+book1.getBName());

        TBook book2 = (TBook)session.get(TBook.class,1);
        System.out.println("图书名称:"+book2.getBName());

        System.out.println(book1==book2);
        tran.commit();
    }catch(Exception e){
        e.printStackTrace();
    }
    finally{
        SessionUtil.close(session);
    }
}

结果:

Hibernate: 
    select
        tbook0_.id as id1_0_0_,
        tbook0_.author as author2_0_0_,
        tbook0_.b_name as b_name3_0_0_,
        tbook0_.b_price as b_price4_0_0_,
        tbook0_.pubDate as pubDate5_0_0_ 
    from
        admindb.t_book tbook0_ 
    where
        tbook0_.id=?
图书名称:红楼梦
图书名称:红楼梦
true

get()和load()缓存可以通用

@Test
public void testGetLoad(){
    Session session = null;
    Transaction tran = null;
    try{
        session = SessionUtil.getSession();
        tran = session.beginTransaction();
        TBook book1 = (TBook)session.get(TBook.class,1);
        System.out.println("图书名称:"+book1.getBName());

        TBook book2 = (TBook)session.load(TBook.class,1);
        System.out.println("图书名称:"+book2.getBName());

        System.out.println(book1==book2);
        tran.commit();
    }catch(Exception e){
        e.printStackTrace();
    }
    finally{
        SessionUtil.close(session);
    }
}

结果:

Hibernate: 
    select
        tbook0_.id as id1_0_0_,
        tbook0_.author as author2_0_0_,
        tbook0_.b_name as b_name3_0_0_,
        tbook0_.b_price as b_price4_0_0_,
        tbook0_.pubDate as pubDate5_0_0_ 
    from
        admindb.t_book tbook0_ 
    where
        tbook0_.id=?
图书名称:红楼梦
图书名称:红楼梦
true

session关闭后,需重新打开,查询发出两条sql(缓存的生命周期与session相同)

@Test
public void testCloseSession(){
    Session session = null;
    Transaction tran = null;
    try{
        session = SessionUtil.getSession();
        tran = session.beginTransaction();
        //发送一条sql
        TBook book = (TBook)session.get(TBook.class,1);
        System.out.println("图书名称:"+book.getBName());
        session.close();
        //需要重新打开
        session = SessionUtil.getSession();
        //发送一条sql
        book = (TBook)session.get(TBook.class,1);
        System.out.println("图书名称:"+book.getBName());

        tran.commit();

    }catch(Exception e){
        e.printStackTrace();
    }
    finally{
        SessionUtil.close(session);
    }
}

结果:

Hibernate: 
    select
        tbook0_.id as id1_0_0_,
        tbook0_.author as author2_0_0_,
        tbook0_.b_name as b_name3_0_0_,
        tbook0_.b_price as b_price4_0_0_,
        tbook0_.pubDate as pubDate5_0_0_ 
    from
        admindb.t_book tbook0_ 
    where
        tbook0_.id=?
图书名称:红楼梦
Hibernate: 
    select
        tbook0_.id as id1_0_0_,
        tbook0_.author as author2_0_0_,
        tbook0_.b_name as b_name3_0_0_,
        tbook0_.b_price as b_price4_0_0_,
        tbook0_.pubDate as pubDate5_0_0_ 
    from
        admindb.t_book tbook0_ 
    where
        tbook0_.id=?
图书名称:红楼梦

list()对于缓存是只存不取

@Test
public void testList1(){
    Session session = null;
    Transaction tran = null;
    try{
        session = SessionUtil.getSession();
        tran = session.beginTransaction();
        List<TBook> list = session.createQuery("from TBook").list();
        for(TBook book : list){
            System.out.println(book.getBName());
        }

        System.out.println("---------------------");
        //session.close();
        list = session.createQuery("from TBook").list();
        for(TBook book : list){
            System.out.println(book.getBName());
        }

        tran.commit();

    }catch(Exception e){
        e.printStackTrace();
    }
    finally{
        SessionUtil.close(session);
    }
}

结果:

Hibernate: select tbook0_.id as id1_0_, tbook0_.author as author2_0_, tbook0_.b_name as b_name3_0_, tbook0_.b_price as b_price4_0_, tbook0_.pubDate as pubDate5_0_ from admindb.t_book tbook0_
红楼梦
资治通鉴
射雕英雄传
百年孤独
傲慢与偏见
---------------------
Hibernate: select tbook0_.id as id1_0_, tbook0_.author as author2_0_, tbook0_.b_name as b_name3_0_, tbook0_.b_price as b_price4_0_, tbook0_.pubDate as pubDate5_0_ from admindb.t_book tbook0_
红楼梦
资治通鉴
射雕英雄传
百年孤独
傲慢与偏见

uniqueResult()对于缓存也是只存不取

@Test
public void testList2(){
    Session session = null;
    Transaction tran = null;
    try{
        session = SessionUtil.getSession();
        tran = session.beginTransaction();
        List<TBook> list = session.createQuery("from TBook").list();
        for(TBook book : list){
            System.out.println(book.getBName());
        }

        System.out.println("---------------------");
        //会再次发送sql
        Object b = session.createQuery("select BName from TBook where id =:id")
                .setInteger("id",1).uniqueResult();
        System.out.println(b);

        tran.commit();

    }catch(Exception e){
        e.printStackTrace();
    }
    finally{
        SessionUtil.close(session);
    }
}

结果:

Hibernate: select tbook0_.id as id1_0_, tbook0_.author as author2_0_, tbook0_.b_name as b_name3_0_, tbook0_.b_price as b_price4_0_, tbook0_.pubDate as pubDate5_0_ from admindb.t_book tbook0_
红楼梦
资治通鉴
射雕英雄传
百年孤独
傲慢与偏见
---------------------
Hibernate: select tbook0_.b_name as col_0_0_ from admindb.t_book tbook0_ where tbook0_.id=?
红楼梦
@Test
public void test1(){
    Session session = null;
    Transaction tran = null;
    try{
        session = SessionUtil.getSession();
        tran = session.beginTransaction();
        Object b = session.createQuery("from TBook where id =:id")
                .setInteger("id",1).uniqueResult();
        System.out.println(b);

        System.out.println("---------------------");


        TBook book = (TBook)session.get(TBook.class,1);
        System.out.println(book.getBName());

        tran.commit();

    }catch(Exception e){
        e.printStackTrace();
    }
    finally{
        SessionUtil.close(session);
    }
}

结果:

Hibernate: select tbook0_.id as id1_0_, tbook0_.author as author2_0_, tbook0_.b_name as b_name3_0_, tbook0_.b_price as b_price4_0_, tbook0_.pubDate as pubDate5_0_ from admindb.t_book tbook0_ where tbook0_.id=?
TBook [id=1, author=曹雪芹, BName=红楼梦, BPrice=60, pubDate=2017-06-15 15:19:19.0]
---------------------
红楼梦

查询部分属性(uniqueResult())

@Test
public void test2(){
    Session session = null;
    Transaction tran = null;
    try{
        session = SessionUtil.getSession();
        tran = session.beginTransaction();
        Object b = session.createQuery("select BName,BPrice from TBook where id =:id")
                .setInteger("id",1).uniqueResult();
        System.out.println(b);

        System.out.println("---------------------");
        //再次发送一条sql
        TBook book = (TBook)session.get(TBook.class,1);
        System.out.println(book.getBName());
        tran.commit();

    }catch(Exception e){
        e.printStackTrace();
    }
    finally{
        SessionUtil.close(session);
    }
}

结果:

Hibernate: select tbook0_.b_name as col_0_0_, tbook0_.b_price as col_1_0_ from admindb.t_book tbook0_ where tbook0_.id=?
[Ljava.lang.Object;@7347bcf4
---------------------
Hibernate: select tbook0_.id as id1_0_0_, tbook0_.author as author2_0_0_, tbook0_.b_name as b_name3_0_0_, tbook0_.b_price as b_price4_0_0_, tbook0_.pubDate as pubDate5_0_0_ from admindb.t_book tbook0_ where tbook0_.id=?
红楼梦

Iterate

@Test
public void test3(){
    Session session = null;
    Transaction tran = null;
    try{
        session = SessionUtil.getSession();
        tran = session.beginTransaction();
        Iterator<TBook> b = session.createQuery("from TBook").iterate();
        if(b.hasNext()){
            System.out.println("图书名称:"+b.next().getBName());
        }

        System.out.println("---------------------");

        TBook book = (TBook)session.get(TBook.class,1);
        System.out.println("图书名称:"+book.getBName());
        tran.commit();

    }catch(Exception e){
        e.printStackTrace();
    }
    finally{
        SessionUtil.close(session);
    }
}

结果:

Hibernate: select tbook0_.id as col_0_0_ from admindb.t_book tbook0_
Hibernate: select tbook0_.id as id1_0_0_, tbook0_.author as author2_0_0_, tbook0_.b_name as b_name3_0_0_, tbook0_.b_price as b_price4_0_0_, tbook0_.pubDate as pubDate5_0_0_ from admindb.t_book tbook0_ where tbook0_.id=?
图书名称:红楼梦
---------------------
图书名称:红楼梦
@Test
public void test4(){
    Session session = null;
    Transaction tran = null;
    try{
        session = SessionUtil.getSession();
        tran = session.beginTransaction();
        Iterator<TBook> book = session.createQuery("from TBook").iterate();
        if(book.hasNext()){
            System.out.println("图书名称:"+book.next().getBName());
        }
        if(book.hasNext()){
            System.out.println("图书名称:"+book.next().getBName());
        }
        System.out.println("---------------------");

        Iterator<TBook> b = session.createQuery("from TBook").iterate();
        if(b.hasNext()){
            System.out.println("图书名称:"+b.next().getBName());
        }
        if(b.hasNext()){
            System.out.println("图书名称:"+b.next().getBName());
        }
        if(b.hasNext()){
            System.out.println("图书名称:"+b.next().getBName());
        }

        tran.commit();

    }catch(Exception e){
        e.printStackTrace();
    }
    finally{
        SessionUtil.close(session);
    }
}

结果:

Hibernate: select tbook0_.id as col_0_0_ from admindb.t_book tbook0_
Hibernate: select tbook0_.id as id1_0_0_, tbook0_.author as author2_0_0_, tbook0_.b_name as b_name3_0_0_, tbook0_.b_price as b_price4_0_0_, tbook0_.pubDate as pubDate5_0_0_ from admindb.t_book tbook0_ where tbook0_.id=?
图书名称:红楼梦
Hibernate: select tbook0_.id as id1_0_0_, tbook0_.author as author2_0_0_, tbook0_.b_name as b_name3_0_0_, tbook0_.b_price as b_price4_0_0_, tbook0_.pubDate as pubDate5_0_0_ from admindb.t_book tbook0_ where tbook0_.id=?
图书名称:资治通鉴
---------------------
Hibernate: select tbook0_.id as col_0_0_ from admindb.t_book tbook0_
图书名称:红楼梦
图书名称:资治通鉴
Hibernate: select tbook0_.id as id1_0_0_, tbook0_.author as author2_0_0_, tbook0_.b_name as b_name3_0_0_, tbook0_.b_price as b_price4_0_0_, tbook0_.pubDate as pubDate5_0_0_ from admindb.t_book tbook0_ where tbook0_.id=?
图书名称:射雕英雄传

二、总结

1、一级缓存是session级别的缓存,生命周期与session相同,session销毁,它也销毁,管理一级缓存,用两个方法:clear()、evict()。

2、两个session不能共享一级缓存,因为它伴随着session的创建与销毁。

3、session缓存是实体级别的,只有在查询对象级别的时候才使用,如果使用Hql或者Sql查询属性级别的,是不能够使用一级缓存的。

4、Iterate查询使用缓存,会发出查询id的sql和hql语句,当使用Iterate的时候,首先就会发出查询id的sql,如果缓存中存在要查询的实体,则直接从缓存中进行取,如果不存在,从数据库中查询,发出一条根据id查询实体的sql,然后将查询的实体放入缓存中,这也就是为什么Iterate会产生N+1查询问题。

5、session的生命周期往往很短,所以存在于session中一级缓存的生命周期也很短,也就意味着,一级缓存的命中率是很低的,对于系统性能的改善也是有限的,当然这个Session内部缓存的主要作用是保持Session内部数据状态同步。并非是hibernate为了大幅提高系统性能所提供的。要想提高系统的性能,我们还是要合理的使用延迟加载,二级缓存等策略。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值