myBatis学习(9):一级缓存和二级缓存
正如大多数持久层框架一样,MyBatis同样提供了一级缓存和二级缓存的支持
1. MyBatis一级缓存基于PerpetualCache的HashMap本地缓存,其存储作用域为 Session,默认情况下,一级缓存是开启状态的。当 Session flush(); 或 close(); 之后,该Session中的所有 Cache 就将清空。
2.MyBatis二级缓存与一级缓存其机制相同,默认也是采用 PerpetualCache,HashMap存储,不同在于其存储作用域为 Mapper(Namespace),并且可自定义存储源,如 Ehcache。
3.对于缓存数据更新机制,当某一个作用域(一级缓存Session/二级缓存Namespaces)的进行了 C/U/D 操作后,默认该作用域下所有 select 中的缓存将被clear。
程序测试一级缓存
usersMapper.xml配置:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.entity.test009.usersMapper"> <select id="myUsers" parameterType="int" resultType="Users">
select * from users where id=#{id}
</select>
<select id="myUpdate" parameterType="Users">
update users set username=#{username},password=#{password} where id=#{id}
</select> </mapper>
写一个获得一级缓存session的工具类:
public class MyBatisUtils { public static SqlSession mySession() throws Exception{ String resource = "conf.xml";
Reader reader = Resources.getResourceAsReader(resource);
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
SqlSession session = factory.openSession(true);
//session.clearCache();//删除缓存
return session;
}
}
测试程序代码
※第1种方法
@Test
public void cacheOne() throws Exception
{
SqlSession session = MyBatisUtils.mySession();
String statement ="com.entity.test009.usersMapper.myUsers"; users = session.selectOne(statement , 3);
System.out.println(users); users = session.selectOne(statement , 3);
System.out.println(users);
//清理session的缓存
session.clearCache();
System.out.println("-----------------------------------");
users = session.selectOne(statement , 3);
System.out.println(users);
}
※运行后的结果:
2015-05-04 22:49:43,323 [main] DEBUG [com.entity.test009.usersMapper.myUsers] - ==> Preparing: select * from users where id=?
2015-05-04 22:49:43,361 [main] DEBUG [com.entity.test009.usersMapper.myUsers] - ==> Parameters: 3(Integer)
2015-05-04 22:49:43,387 [main] DEBUG [com.entity.test009.usersMapper.myUsers] - <== Total: 1
Users [id=3, username=张三, password=123456, age=99, sex=0]
Users [id=3, username=张三, password=123456, age=99, sex=0]
--------------------- //session.clearCache();后又一次查询了数据库,并非从缓存中读取数据
2015-05-04 22:49:43,388 [main] DEBUG [com.entity.test009.usersMapper.myUsers] - ==> Preparing: select * from users where id=?
2015-05-04 22:49:43,389 [main] DEBUG [com.entity.test009.usersMapper.myUsers] - ==> Parameters: 3(Integer)
2015-05-04 22:49:43,390 [main] DEBUG [com.entity.test009.usersMapper.myUsers] - <== Total: 1
Users [id=3, username=张三, password=123456, age=99, sex=0]
※第2种方法
@Test
public void cacheOne() throws Exception
{
SqlSession session = MyBatisUtils.mySession();
String statement ="com.entity.test009.usersMapper.myUsers"; users = session.selectOne(statement , 3);
System.out.println(users); users = session.selectOne(statement , 3);
System.out.println(users);
/**
* 第2个方法,执行一个更新的操作
*/
session.update("com.entity.test009.usersMapper.myUpdate", new Users(3, "张三", "123456", null, null));
session.commit();
System.out.println("---------------------");
users = session.selectOne(statement , 3);
System.out.println(users);
}
※运行后的结果:
2015-05-04 22:55:38,685 [main] DEBUG [com.entity.test009.usersMapper.myUsers] - ==> Preparing: select * from users where id=?
2015-05-04 22:55:38,724 [main] DEBUG [com.entity.test009.usersMapper.myUsers] - ==> Parameters: 3(Integer)
2015-05-04 22:55:38,747 [main] DEBUG [com.entity.test009.usersMapper.myUsers] - <== Total: 1
Users [id=3, username=张三, password=123456, age=99, sex=0]
Users [id=3, username=张三, password=123456, age=99, sex=0]
2015-05-04 22:55:38,748 [main] DEBUG [com.entity.test009.usersMapper.myUpdate] - ==> Preparing: update users set username=?,password=? where id=?
2015-05-04 22:55:38,749 [main] DEBUG [com.entity.test009.usersMapper.myUpdate] - ==> Parameters: 张三(String), 123456(String), 3(Integer)
2015-05-04 22:55:38,749 [main] DEBUG [com.entity.test009.usersMapper.myUpdate] - <== Updates: 1
---------------------//大家可以看出来,执行完更新后,一级缓存会被自动清理,然后下边又一次查询数据库
2015-05-04 22:55:38,750 [main] DEBUG [com.entity.test009.usersMapper.myUsers] - ==> Preparing: select * from users where id=?
2015-05-04 22:55:38,750 [main] DEBUG [com.entity.test009.usersMapper.myUsers] - ==> Parameters: 3(Integer)
2015-05-04 22:55:38,751 [main] DEBUG [com.entity.test009.usersMapper.myUsers] - <== Total: 1
Users [id=3, username=张三, password=123456, age=99, sex=0]
※第3种方法
@Test
public void cacheOne() throws Exception
{
SqlSession session = MyBatisUtils.mySession();
String statement ="com.entity.test009.usersMapper.myUsers"; users = session.selectOne(statement , 3);
System.out.println(users); users = session.selectOne(statement , 3);
System.out.println(users); /**
* 第3个方法,并非同一个session对象。关闭session后,重新再开一个session2。这个时候和刚才的不一样,所以就不会用session刚才的缓存了
*/
session.close();
SqlSession session2 = MyBatisUtils.mySession(); System.out.println("---------------------");
users = session2.selectOne(statement , 3);
System.out.println(users);
}
※运行后的结果:
2015-05-04 23:06:25,518 [main] DEBUG [com.entity.test009.usersMapper.myUsers] - ==> Preparing: select * from users where id=?
2015-05-04 23:06:25,557 [main] DEBUG [com.entity.test009.usersMapper.myUsers] - ==> Parameters: 3(Integer)
2015-05-04 23:06:25,580 [main] DEBUG [com.entity.test009.usersMapper.myUsers] - <== Total: 1
Users [id=3, username=张三, password=123456, age=99, sex=0]
Users [id=3, username=张三, password=123456, age=99, sex=0]
---------------------//重新获取session,这个session2重新从数据库查询一条数据出来
2015-05-04 23:06:25,794 [main] DEBUG [com.entity.test009.usersMapper.myUsers] - ==> Preparing: select * from users where id=?
2015-05-04 23:06:25,794 [main] DEBUG [com.entity.test009.usersMapper.myUsers] - ==> Parameters: 3(Integer)
2015-05-04 23:06:25,795 [main] DEBUG [com.entity.test009.usersMapper.myUsers] - <== Total: 1
Users [id=3, username=张三, password=123456, age=99, sex=0]
二级缓存测试(默认关闭状态)
首先在usersMapper.xml开启
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.entity.test009.usersMapper">
<cache/>
<select id="myUsers" parameterType="int" resultType="Users">
select * from users where id=#{id}
</select> <select id="myUpdate" parameterType="Users">
update users set username=#{username},password=#{password} where id=#{id}
</select> </mapper>
然后新建一个创建工厂的工具类,返回一个factory,这样创建出来的session就不一样。
public class CopyOfMyBatisUtils { public static SqlSessionFactory factory() throws Exception{ String resource = "conf.xml";
Reader reader = Resources.getResourceAsReader(resource);
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
return factory;
}
}
测试代码:
@Test
public void cacheTwo() throws Exception
{ String statement ="com.entity.test009.usersMapper.myUsers"; SqlSessionFactory factory = CopyOfMyBatisUtils.factory();
SqlSession session1 = factory.openSession();
SqlSession session2 = factory.openSession(); users = session1.selectOne(statement , 6);
session1.commit();//需要提交事物,否则二级缓存无效
System.out.println(users); System.out.println("****************************"); users = session1.selectOne(statement , 6);
session2.commit();
System.out.println(users); }
运行结果:
2015-05-04 23:45:21,750 [main] DEBUG [com.entity.test009.usersMapper] - Cache Hit Ratio [com.entity.test009.usersMapper]: 0.0
2015-05-04 23:45:22,035 [main] DEBUG [com.entity.test009.usersMapper.myUsers] - ==> Preparing: select * from users where id=?
2015-05-04 23:45:22,079 [main] DEBUG [com.entity.test009.usersMapper.myUsers] - ==> Parameters: 6(Integer)
2015-05-04 23:45:22,100 [main] DEBUG [com.entity.test009.usersMapper.myUsers] - <== Total: 1
Users [id=6, username=张3, password=654321, age=99, sex=0]
****************************
2015-05-04 23:45:22,109 [main] DEBUG [com.entity.test009.usersMapper] - Cache Hit Ratio 缓存命中率 [com.entity.test009.usersMapper]: 0.5 百分比
Users [id=6, username=张3, password=654321, age=99, sex=0]
补充说明:
映射语句文件中的所有select语句将会被缓存。
映射语句文件中的所有insert,update和delete语句会刷新缓存。
缓存会使用Least Recently Used(LRU,最近最少使用的)算法来收回。
根据时间表(比如no Flush Interval,没有刷新间隔),缓存不会以任何时间顺序来刷新。
缓存会存储列表集合或对象(无论查询方法返回什么)的1024个引用。
缓存会被视为是read/write(可读/可写)的缓存,意味着对象检索不是共享的,而且可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改
<cache eviction="FIFO" //回收策略为先进先出 flushInterval="60000" //自动刷新时间60s size="512" //最多缓存512个引用对象 readOnly="true" //只读
/>
myBatis学习(9):一级缓存和二级缓存的更多相关文章
- mybatis源码学习:一级缓存和二级缓存分析
目录 零.一级缓存和二级缓存的流程 一级缓存总结 二级缓存总结 一.缓存接口Cache及其实现类 二.cache标签解析源码 三.CacheKey缓存项的key 四.二级缓存TransactionCa ...
- Mybatis学习(五)————— 延迟加载和缓存机制(一级二级缓存)
一.延迟加载 延迟加载就是懒加载,先去查询主表信息,如果用到从表的数据的话,再去查询从表的信息,也就是如果没用到从表的数据的话,就不查询从表的信息.所以这就是突出了懒这个特点.真是懒啊. Mybati ...
- 9.Mybatis一级缓存和二级缓存
所谓的缓存呢?其实原理很简单,就是在保证你查询的数据是正确的情况下,没有去查数据库,而是直接查找的内存,这样做有利于缓解数据库的压力,提高数据库的性能,Mybatis中有提供一级缓存和二级缓存. 学习 ...
- [原创]关于mybatis中一级缓存和二级缓存的简单介绍
关于mybatis中一级缓存和二级缓存的简单介绍 mybatis的一级缓存: MyBatis会在表示会话的SqlSession对象中建立一个简单的缓存,将每次查询到的结果结果缓存起来,当下次查询的时候 ...
- MyBatis 延迟加载,一级缓存,二级缓存设置
什么是延迟加载 resultMap中的association和collection标签具有延迟加载的功能. 延迟加载的意思是说,在关联查询时,利用延迟加载,先加载主信息.使用关联信息时再去加载关联信息 ...
- mybatis高级(3)_延迟加载_深度延迟_一级缓存_二级缓存
设置延迟加载需要在mybatis.xml中设置 注: 侵入式延迟加载为真时是延迟加载 侵入式延迟加载为假时是深度延迟加载 <!-- 延迟加载和深度延迟加载 --> <settings ...
- 八 mybatis查询缓存(一级缓存,二级缓存)和ehcache整合
1 查询缓存 1.1 什么是查询缓存 mybatis提供查询缓存,用于减轻数据压力,提高数据库性能. mybaits提供一级缓存,和二级缓存.
- mybatis 详解(九)------ 一级缓存、二级缓存
上一章节,我们讲解了通过mybatis的懒加载来提高查询效率,那么除了懒加载,还有什么方法能提高查询效率呢?这就是我们本章讲的缓存. mybatis 为我们提供了一级缓存和二级缓存,可以通过下图来理解 ...
- MyBatis从入门到放弃六:延迟加载、一级缓存、二级缓存
前言 使用ORM框架我们更多的是使用其查询功能,那么查询海量数据则又离不开性能,那么这篇中我们就看下mybatis高级应用之延迟加载.一级缓存.二级缓存.使用时需要注意延迟加载必须使用resultMa ...
随机推荐
- UINavigation push 于 present到另一个页面详解
如果页面中没有导航栏,可以present到这个A页面,在A页面想要跳转到有个有导航栏的页面就需要添加给B页面添加一个UINavigationController 然后present到B页面,代码如下 ...
- Xcode7真机测试
根据这个网址上的步骤能够完成真机测试,我已经试过了,还不错 http://www.bubuko.com/infodetail-1061938.html
- 我的创业劲儿,无可阻挡-JAVA学院张孝伟
导语:张孝伟,这个怀揣着创业梦想的农村小伙,为了报答父母的恩情,他开启了自己的逐梦之旅.友好的伙伴,火旺的生意.以前让他如鱼得水.就在他满足于现状的时候,一场突如其来的事故,让他一夜间倾家荡产.他是否 ...
- _getch() 和 getch() 及 _T()
带下划线_的函数一般是函数库内部的函数,而不带下划线的一般是提供给用户使用的函数.带下划线的目的是为了防止用户定义的函数和函数库的函数重名冲突,所以直接使用也是可以的.要用getch()必须引入头文件 ...
- DES加解密算法Qt实现
算法解密qt加密table64bit [声明] (1) 本文源码 大部分源码来自:DES算法代码.在此基础上,利用Qt编程进行了改写,实现了DES加解密算法,并添加了文件加解密功能.在此对署名为b ...
- openOffice安装
[root@rusky openOffice]# tar -zxvf OOo_3..0_Linux_x86_install-rpm-wJRE_zh-CN.tar.gz [root@rusky open ...
- css快捷方式
本来是年前准备整理发布的,都搞定50%了,一篇万恶的<盗墓笔记:九幽将军>让我猪油蒙了心.....诶,不说了,搞一半就算了,最后还忘了保存,此刻只听得那一万只草某马呼啸而过... 言归正传 ...
- python 元类与定制元类
1:元类 元类:类的创建与管理者 所有类的元类是type class a: pass print(type(a)) 结果:<class 'type'> 2:定制元类 类的实例化过程:(可看 ...
- (转)asp.net动态设置标题title 关键字keywords 描述descrtptions
方法一 if (!IsPostBack){//Page title网页标题Page.Title = “我的网站标题”;//须将网页head标签设成服务器控件模式,即<head runat=&qu ...
- (转)SQL中的ISNULL函数介绍
SQL中有多种多样的函数,下面将为您介绍SQL中的ISNULL函数,包括其语法.注释.返回类型等,供您参考,希望对您学习SQL能够有所帮助. ISNULL 使用指定的替换值替换 NULL. 语法ISN ...