mybatis的二级缓存和hibernate的三级缓存

目录

Mybatis缓存 2

一、MyBatis缓存介绍 2

1.导包: 2

2一级缓存代码 2

3.二级缓存代码 3

4、二级缓存补充说明 4

Hibernate 缓存 4

Hibernate 所有缓存机制详解 4

1.导包 5

2.一级缓存代码 5

3.二级缓存代码 6

4. 三级缓存代码 6

5. 一级缓存 二级缓存 三级缓存 之间的比较 7

 


Mybatis缓存

一、MyBatis缓存介绍

  正如大多数持久层框架一样,MyBatis 同样提供了一级缓存二级缓存的支持.

1. 一级缓存: 基于PerpetualCache HashMap本地缓存,其存储作用域为 Session,当 Session flush close 之后,该Session中的所有 Cache 就将清空

  2. 二级缓存与一级缓存其机制相同,默认也是采用 PerpetualCacheHashMap存储,不同在于其存储作用域为 Mapper(Namespace)并且可自定义存储源,如 Ehcache

  3. 对于缓存数据更新机制,当某一个作用域(一级缓存Session/二级缓存Namespaces)的进行了 C/U/D 操作后,默认该作用域下所有 select 中的缓存将被clear

 

1.导包:

 

2一级缓存代码

public static void main(String[] args) {

InputStream as = Test1.class.getClassLoader().getResourceAsStream("mybatis-config.xml");

    SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(as);

    

    SqlSession session = sessionFactory.openSession();

    SqlSession session2 = sessionFactory.openSession();

    

    

    Object obj1 = session.selectOne("user.getObjectById",1);

    Object obj2 = session2.selectOne("user.getObjectById",1);

    

    System.out.println(obj1);

    System.out.println(obj2);

    

    //session关闭

    session.close();

    session2.close();

}

 

运行结果:

 

3.二级缓存代码

public static void main(String[] args) {

   

    InputStream as = Test1.class.getClassLoader().getResourceAsStream("mybatis-config.xml");

    SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(as);

    

    //开启两个不同的session

    SqlSession session = sessionFactory.openSession();

    SqlSession session2 = sessionFactory.openSession();

    

  //使用二级缓存时,User类必须实现一个Serializable接口===> User implements Serializable

    Object obj1 = session.selectOne("user.getObjectById",1);

    

    session.commit();//这个地方一定要提交事务之后二级缓存才会起作用

    Object obj2 = session2.selectOne("user.getObjectById",1);

    

    System.out.println(obj1);

    System.out.println(obj2);

    

    //session关闭

    session.close();

    session2.close();

    

}

public static void main(String[] args) {

    InputStream as = Test1.class.getClassLoader().getResourceAsStream("mybatis-config.xml");

    SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(as);

    

    //开启两个不同的session

    SqlSession session = sessionFactory.openSession();

    SqlSession session2 = sessionFactory.openSession();

    

  //使用二级缓存时,User类必须实现一个Serializable接口===> User implements Serializable

    Object obj1 = session.selectOne("user.getObjectById",1);

    session.commit();//这个地方一定要提交事务之后二级缓存才会起作用

    Object obj2 = session2.selectOne("user.getObjectById",1);

    

    System.out.println(obj1);

    System.out.println(obj2);

    

    //session关闭

    session.close();

    session2.close();

 

}

运行结果:

 

4、二级缓存补充说明

  1. 映射语句文件中的所有select语句将会被缓存。

  2. 映射语句文件中的所有insertupdatedelete语句会刷新缓存。

  3. 缓存会使用Least Recently UsedLRU,最近最少使用的)算法来收回。

  4. 缓存会根据指定的时间间隔来刷新。

  5. 缓存会存储1024个对象

cache标签常用属性:

<cache eviction="FIFO"  <!--回收策略为先进先出-->

flushInterval="60000" <!--自动刷新时间60s-->

size="512" <!--最多缓存512个引用对象-->

readOnly="true"/> <!--只读-->

 

Hibernate 缓存

Hibernate 所有缓存机制详解 

hibernate提供的一级缓存

hibernate是一个线程对应一个session,一个线程可以看成一个用户。也就是说session级缓存(一级缓存)只能给一个线程用,别的线程用不了,一级缓存就是和线程绑定了。

hibernate一级缓存生命周期很短,和session生命周期一样,一级缓存也称session级的缓存或事务级缓存。如果tb事务提交或回滚了,我们称session就关闭了,生命周期结束了。

缓存和连接池的区别:缓 存和池都是放在内存里,实现是一样的,都是为了提高性能的。但有细微的差别,池是重量级的,里面的数据是一样的,比如一个池里放100Connection连接对象,这个100个都是一样的。缓存里的数据,每个都不一样。比如读取100条数据库记录放到缓存里,这100条记录都不一样。

 

1.导包

 

2.一级缓存代码

public static void main(String[] args) {

       Configuration cfg = new Configuration();

       SessionFactory factory = cfg.configure("hibernate1.cfg.xml").buildSessionFactory();

       Session session1= factory.openSession();

   

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

       

       //第二次查询第一次相同的数据,第二次不会发出sql语句查询数据库,而是到缓存里取数据。

       User user2 = (User)session1.get(User.class, 1);

       System.out.println(user);

       System.out.println(user2);

       

       //关闭sesssion 释放一级缓存

       session1.close();

       factory.close();

}

运行结果:

 

 

3.二级缓存代码

public static void main(String[] args) {

       Configuration cfg = new Configuration();

       SessionFactory factory = cfg.configure("hibernate2.cfg.xml").buildSessionFactory();

       Session session1= factory.openSession();

       Session session2= factory.openSession();

   

       User user1 =(User)session1.load(User.class, 1);

       User user2 =(User) session2.load(User.class, 1);

       

       System.out.println(user1.getName());

       System.out.println(user2.getName());

       

       //关闭session  释放二级缓存

       session1.close();

       session2.close();

       factory.close();

}

 

注:<cache usage="read-only"/>

运行结果:

 

可见,二级缓存是起作用了的。用get测试是同样的结果。

4.三级缓存代码

public static void main(String[] args) {

       Configuration cfg = new Configuration();

       SessionFactory factory = cfg.configure("hibernate3.cfg.xml").buildSessionFactory();

       Session session1= factory.openSession();

   

       Query query1 = session1.createQuery("FROM User");

       query1.setCacheable(true);

//       List list1 = query1.list();

       Iterator iterate1 = query1.iterate();

       

       Query query2 = session1.createQuery("FROM User");

       query2.setCacheable(true);

//       List list2 = query2.list();

       Iterator iterate2 = query2.iterate();

       

       System.out.println(iterate1);

       System.out.println(iterate2);

       

       //关闭session  释放三级缓存

       session1.close();

       factory.close();

}

运行结果:

 

 

5.一级缓存 二级缓存 三级缓存 之间的比较

一级缓存(session级的缓存):在一个session中load同一个对象2次,load时,hibernate首先在session缓存中查找对象,如果没找到就到数据库中去load。因此,在同一个session中load一个对象2次,只会发出一条sql语句。而在2个session中load同一个对象则会发送2次sql语句。

二级缓存(session的公用缓存,sessionFactory级别的缓存,jvm级缓存):hibernate支持多种二级缓存,hibernate提供了一个HashTable,用于测试,不建议运用与产品中。

 

二级缓存适合放什么对象呢?

 

①经常被访问(这个对象经常被访问,如果每次都到数据库去取,会降低效率)

②改动不大(这个对象改动不大,如果改动较大,就可能造成缓存数据跟数据库中的数据不一致)

 

三级缓存(查询缓存):如果要使Query使用二级缓存,则需要打开查询缓存。事实上,三级缓存是基于二级缓存的,如:list(集合),默认情况,它只会往二级缓存中存放数据,查找时不会搜索二级缓存,这是因为查询条件会随时变化。有一种情况就是2次查询的条件是一样的,这是要想使用二级缓存,就必须打开查询缓存,打开方式如:

 

<property name="cache.use_query_cache">true</property>

然后加上:setCachabletrue

 

缓存算法有:

LRU(Least Recently Used):这种算法是在每个对象中维护一个访问的时间变量,每次访问后,时间都会更新,当新的对象需要存放到缓存时,替换那个按时间排序最后的对象。

LFU(Least Frequently Used):这种算法是每个对象记录了对象访问的次数(即命中率),当新的对象需要存放到缓存时,替换那个访问次数最少的对象。

FIFO(First In First Out):这种算法是将缓存中的对象存放成一个数组,当新的对象需要存放到内存中是,替换最先存放到缓存的对象。

使用时通常在缓存配置文件中加入:MemoryStoreEvictionPolicy="LRU"

listiterate存放的不同之处:

①List:直接取出所有的记录将其封装成对象放到集合中。

Iterator:先取出所有记录的id(主键),当需要用到对应的id的记录时,再根据id发sql语句。②list不会主动利用session级的缓存,因此list遍历时每次会到数据库中取数据。

Iterator会利用session的缓存,Iterator每次会到缓存中找,如果缓存中没有,再到数据库中取数据。

③Iterator默认使用二级缓存

list默认往二级缓存存数据,但是查询时不使用二级缓存。

 

你可能感兴趣的:(mybatis的二级缓存和hibernate的三级缓存)