MyBatis Review——查询缓存

一,查询缓存简介

mybatis提供查询缓存,用于减轻数据压力,提高数据库性能。

mybaits提供一级缓存,和二级缓存。

一级缓存是SqlSession级别的缓存。在操作数据库时候,需要构造sqlSession对象,在对象中有一个数据结构(HashMap)用于存储缓存数据。不同的sqlSession之间的缓存数据区域是互相不影响的。

二级缓存是mapper级别的缓存,多个sqlSession去操作同一个mapper的sql语句,多个sqlSession可以共用二级缓存,二级缓存是跨sqlSession的。

二,一级缓存

1,一级缓存的原理

步骤:

1,第一次发起查询用户id为1的信息,先去缓存中查找是否存在id为1的信息,如果没有,发出sq语句,从数据库查询用户信息。得到用户信息,将用户信息存储到一级缓存中。

2,如果sqlSession去执行commit操作(执行插入,更新,删除),清空sqlSession中的一级缓存,这样做的目的是为了让缓存中存储最新的信息,避免脏读。

3,当第二次查询用户id为1的信息的时候,先去缓存中查找是否有id为1的用户信息,缓存中有,则直接从缓存中取数据,不再发出sql查询语句。

2,一级缓存的测试

1,测试没有commit操作的时候,从缓存取得数据:

@Test
	public void testCache1() throws Exception {
		SqlSession sqlSession=sqlSessionFactory.openSession();
		//创建代理对象
		UserMapper userMapper=sqlSession.getMapper(UserMapper.class);

		//第一次发起请求,查询id为1的用户
		User user1=userMapper.findUserById(1);
		System.out.println(user1.toString());

		//第二次发起请求,查询id为1的用户
		User user2=userMapper.findUserById(1);
		System.out.println(user2.toString());

		sqlSession.close();
	}

debug信息:

DEBUG [main] - Cache Hit Ratio [cn.itcast.mybatis.mapper.UserMapper]: 0.0
DEBUG [main] - Opening JDBC Connection
DEBUG [main] - Created connection 819131219.
DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@30d2f353]
DEBUG [main] - ==>  Preparing: SELECT * FROM user where id=?
DEBUG [main] - ==> Parameters: 1(Integer)
DEBUG [main] - <==      Total: 1
cn.itcast.mybatis.po.User@68d9915
DEBUG [main] - Cache Hit Ratio [cn.itcast.mybatis.mapper.UserMapper]: 0.0
cn.itcast.mybatis.po.User@68d9915
DEBUG [main] - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@30d2f353]
DEBUG [main] - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@30d2f353]
DEBUG [main] - Returned connection 819131219 to pool.

第一次查询id=1,发出一条sql语句,之后在第二次查询的时候,没有任何sql语句。

2,测试存在commit操作的时候,缓存变化

@Test
	public void testCache1() throws Exception {
		SqlSession sqlSession=sqlSessionFactory.openSession();
		//创建代理对象
		UserMapper userMapper=sqlSession.getMapper(UserMapper.class);

		//第一次发起请求,查询id为1的用户
		User user1=userMapper.findUserById(1);
		System.out.println(user1.toString());

		/*如果sqlSession去执行commit操作,(插入,删除,更新),清空sqlSession的
		  一级缓存,这样做的目的是为了让缓存中存储的是最新信息,避免脏读
		  */
		user1.setAddress("故宫");

		userMapper.updateUser(user1);
		sqlSession.commit();//清空缓存

		//第二次发起请求,查询id为1的用户
		User user2=userMapper.findUserById(1);
		System.out.println(user2.toString());

		sqlSession.close();
	}
	

deubg信息:

DEBUG [main] - Checking to see if class cn.itcast.mybatis.mapper.UserMapperTest matches criteria [is assignable to Object]
DEBUG [main] - Cache Hit Ratio [cn.itcast.mybatis.mapper.UserMapper]: 0.0
DEBUG [main] - Opening JDBC Connection
DEBUG [main] - Created connection 538784332.
DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@201d324c]
DEBUG [main] - ==>  Preparing: SELECT * FROM user where id=?
DEBUG [main] - ==> Parameters: 1(Integer)
DEBUG [main] - <==      Total: 1
cn.itcast.mybatis.po.User@3eb6e46
DEBUG [main] - ==>  Preparing: update user set username=?,birthday=?,sex=?,address=? where id=?
DEBUG [main] - ==> Parameters: lhccccccccc(String), 2016-05-21 00:00:00.0(Timestamp), 1(String), 故宫(String), 1(Integer)
DEBUG [main] - <==    Updates: 1
DEBUG [main] - Committing JDBC Connection [com.mysql.jdbc.JDBC4Connection@201d324c]
DEBUG [main] - Cache Hit Ratio [cn.itcast.mybatis.mapper.UserMapper]: 0.0
DEBUG [main] - ==>  Preparing: SELECT * FROM user where id=?
DEBUG [main] - ==> Parameters: 1(Integer)
DEBUG [main] - <==      Total: 1
cn.itcast.mybatis.po.User@4e30cbae
DEBUG [main] - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@201d324c]
DEBUG [main] - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@201d324c]
DEBUG [main] - Returned connection 538784332 to pool.

在update语句执行之后,当再次查询id=1的时候,又发出sql语句。

3,一级缓存的应用

正式开发,是将mybatis和spring进行整合开发,事务控制在service中。

一个service方法中包括 很多mapper方法调用。

service{

//开始执行时,开启事务,创建SqlSession对象

//第一次调用mapper的方法findUserById(1)

//第二次调用mapper的方法findUserById(1),从一级缓存中取数据

//方法结束,sqlSession关闭

}

如果是执行两次service调用查询相同 的用户信息,不走一级缓存,因为session方法结束,sqlSession就关闭,一级缓存就清空。

三,二级缓存

1,原理

使用二级缓存步骤:

首先开启mybatis的二级缓存:

sqlSession1去查询id=1的用户信息,发出sql语句,查询到的结果会被放入二级缓存。

如果sqlSession3去执行相同mapper的sql,执行commit提交,清空该mapper下的二级缓存区域的数据。

sqlSession2区查询用户id为1的信息,去缓存中查找是否存在数据,如果存在则直接从缓存中取数据。

二级缓存与一级缓存区别:二级缓存范围更大,多个sqlSession可以共享一个UserMapper的二级缓存区域。UserMapper又一个二级缓存区域(按照namespace分),其他mapper也有自己的二级缓存区域(按照namespace分)。每一个namespace的mapper都有一个二级缓存区域,两个mapper的namespace如果相同,这两个mapper执行sql查询到数据将存在相同 的二级缓存区域中。

2,开启二级缓存

开启了settings中的全局二级缓存配置后,如果某个mapper要开启二级缓存,需要在mapper的xml中加入:

	<!-- 开启本mapper的namespace下的二级缓存 -->
	<cache/>

pojo类实现序列化接口:

(ps:为了将缓存数据取出执行反序列化操作,因为二级缓存数据存储介质多种多样,不一样在内存。)

3,测试代码

@Test
	public void testCache2() throws Exception {
		SqlSession sqlSession1=sqlSessionFactory.openSession();
		SqlSession sqlSession2=sqlSessionFactory.openSession();
		SqlSession sqlSession3=sqlSessionFactory.openSession();

		//创建代理对象
		UserMapper userMapper1=sqlSession1.getMapper(UserMapper.class);
		UserMapper userMapper2=sqlSession2.getMapper(UserMapper.class);
		UserMapper userMapper3=sqlSession2.getMapper(UserMapper.class);
		//第一次发起请求,查询id为1的用户
		User user1=userMapper1.findUserById(1);
		System.out.println(user1.toString());

		//这里执行关闭操作,将sqlSession中数据写入二级缓存中去
		sqlSession1.close();

		//第二次发起请求,查询id为1的用户
		User user2=userMapper2.findUserById(1);
		System.out.println(user2.toString());

		sqlSession2.close();

	}

输出信息:

DEBUG [main] - Cache Hit Ratio [cn.itcast.mybatis.mapper.UserMapper]: 0.0
DEBUG [main] - Opening JDBC Connection
DEBUG [main] - Created connection 1602614455.
DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@5f85f4b7]
DEBUG [main] - ==>  Preparing: SELECT * FROM user where id=?
DEBUG [main] - ==> Parameters: 1(Integer)
DEBUG [main] - <==      Total: 1
cn.itcast.mybatis.po.User@1a6778eb
DEBUG [main] - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@5f85f4b7]
DEBUG [main] - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@5f85f4b7]
DEBUG [main] - Returned connection 1602614455 to pool.
DEBUG [main] - Cache Hit Ratio [cn.itcast.mybatis.mapper.UserMapper]: 0.5
cn.itcast.mybatis.po.User@7b781fdd

只有第一次发出了sql语句,第二次并没有去查询。

加入带有commit操作的代码:

@Test
	public void testCache2() throws Exception {
		SqlSession sqlSession1=sqlSessionFactory.openSession();
		SqlSession sqlSession2=sqlSessionFactory.openSession();
		SqlSession sqlSession3=sqlSessionFactory.openSession();

		//创建代理对象
		UserMapper userMapper1=sqlSession1.getMapper(UserMapper.class);
		UserMapper userMapper2=sqlSession2.getMapper(UserMapper.class);
		UserMapper userMapper3=sqlSession2.getMapper(UserMapper.class);
		//第一次发起请求,查询id为1的用户
		User user1=userMapper1.findUserById(1);
		System.out.println(user1.toString());

		//这里执行关闭操作,将sqlSession中数据写入二级缓存中去
		sqlSession1.close();

		/*使用sqlSession3执行commit操作*/
		User user=userMapper3.findUserById(1);
		user.setAddress("(>﹏<");
		userMapper3.updateUser(user);
		//执行提交清空二级缓存
		sqlSession3.commit();
		sqlSession3.close();

		//第二次发起请求,查询id为1的用户
		User user2=userMapper2.findUserById(1);
		System.out.println(user2.toString());

		sqlSession2.close();

	}

输出信息:

DEBUG [main] - Cache Hit Ratio [cn.itcast.mybatis.mapper.UserMapper]: 0.0
DEBUG [main] - Opening JDBC Connection
DEBUG [main] - Created connection 447056233.
DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1aa58969]
DEBUG [main] - ==>  Preparing: SELECT * FROM user where id=?
DEBUG [main] - ==> Parameters: 1(Integer)
DEBUG [main] - <==      Total: 1
cn.itcast.mybatis.po.User@c355f75
DEBUG [main] - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1aa58969]
DEBUG [main] - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@1aa58969]
DEBUG [main] - Returned connection 447056233 to pool.
DEBUG [main] - Cache Hit Ratio [cn.itcast.mybatis.mapper.UserMapper]: 0.5
DEBUG [main] - Opening JDBC Connection
DEBUG [main] - Checked out connection 447056233 from pool.
DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1aa58969]
DEBUG [main] - ==>  Preparing: update user set username=?,birthday=?,sex=?,address=? where id=?
DEBUG [main] - ==> Parameters: lhccccccccc(String), 2016-05-21 00:00:00.0(Timestamp), 1(String), (>﹏<(String), 1(Integer)
DEBUG [main] - <==    Updates: 1
DEBUG [main] - ==>  Preparing: SELECT * FROM user where id=?
DEBUG [main] - ==> Parameters: 1(Integer)
DEBUG [main] - <==      Total: 1
cn.itcast.mybatis.po.User@320e64a7
DEBUG [main] - Rolling back JDBC Connection [com.mysql.jdbc.JDBC4Connection@1aa58969
DEBUG [main] - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1aa58969]
DEBUG [main] - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@1aa58969]
DEBUG [main] - Returned connection 447056233 to pool.

代码中加入了需要commit的更改操作,二级缓存被更新,查询时候需要重新发出sql语句。

四,一些其他配置

1,禁用二级缓存

<select id="findUserById" parameterType="int"
		resultType="cn.itcast.mybatis.po.User" useCache="false">
		SELECT * FROM user where id=#{value}
	</select>

在某个statement中设置usecache="false"会禁用当前二级缓存,即每次都会发出sql去查询新数据。默认情况是true.

2,刷新缓存(清空)

在mapper的同一个namespace中,如果有其它insert、update、delete操作数据后需要刷新缓存,如果不执行刷新缓存会出现脏读。

设置statement配置中的flushCache="true" 属性,默认情况下为true即刷新缓存,如果改成false则不会刷新。使用缓存时如果手动修改数据库表中的查询数据会出现脏读。

<insert id="insertUser" parameterType="cn.itcast.mybatis.po.User" flushCache="true">

一般下执行完commit操作都需要刷新缓存,flushCache=true表示刷新缓存,这样可以避免数据库脏读。

时间: 2024-07-29 21:59:40

MyBatis Review——查询缓存的相关文章

MyBatis学习--查询缓存

简介 以前在使用Hibernate的时候知道其有一级缓存和二级缓存,限制ORM框架的发展都是互相吸收其他框架的优点,在Hibernate中也有一级缓存和二级缓存,用于减轻数据压力,提高数据库性能. mybaits提供一级缓存和二级缓存结构如下图: 可以看出一级缓存是sqlSession级别的,而二级缓存是Mapper级别的,同一个Mapper中的多个sqlSession可以共享缓存数据. 一级缓存是SqlSession级别的缓存.在操作数据库时需要构造 sqlSession对象,在对象中有一个数

mybatis查询缓存——(十三)

1.     mybatis缓存介绍 如下图,是mybatis一级缓存和二级缓存的区别图解: mybatis提供查询缓存,用于减轻数据压力,提高数据库性能. mybaits提供一级缓存,和二级缓存. 一级缓存是SqlSession级别的缓存.在操作数据库时需要构造 sqlSession对象,在对象中有一个数据结构(HashMap)用于存储缓存数据.不同的sqlSession之间的缓存数据区域(HashMap)是互相不影响的. 二级缓存是mapper级别的缓存,多个SqlSession去操作同一个

mybatis入门基础(八)-----查询缓存

阅读目录 一.什么是查询缓存 二.一级缓存 三.二级缓存 回到顶部 一.什么是查询缓存 mybatis提供查询缓存,用于减轻数据压力,提高数据库性能. mybaits提供一级缓存,和二级缓存. 1.1. 一级缓存是sqlSession级别的缓存.在操作数据库时需要构造sqlSession对象,在对象中有一个数据结构(HashMap),用于存储缓存数据.不同的sqlSession之间的缓存 区域(HashMap)是互不影响的. 1.2. 二级缓存是mapper级别的缓存,多个sqlSession去

Spring+SpringMVC+MyBatis深入学习及搭建(八)——MyBatis查询缓存

1.什么是查询缓存 mybatis提供查询缓存,用于减轻数据库压力,提高数据库性能. mybatis提供一级缓存和二级缓存. 一级缓存是SqlSession级别的缓存.在操作数据库时需要构造sqlSession对象,在对象中有一个数据结构(HashMap)用于存储缓存数据.不同的sqlSession之间的缓存数据区域(HashMap)是互相不影响的. 二级缓存是mapper级别的缓存,多个sqlSession去操作同一个Mapper的sql语句,多个sqlSession可以共用二级缓存,二级缓存

mybatis学习笔记(14)-查询缓存之中的一个级缓存

mybatis学习笔记(14)-查询缓存之中的一个级缓存 mybatis学习笔记14-查询缓存之中的一个级缓存 查询缓存 一级缓存 一级缓存工作原理 一级缓存測试 一级缓存应用 本文主要讲mybatis的一级缓存.一级缓存是SqlSession级别的缓存. 查询缓存 mybatis提供查询缓存.用于减轻数据压力,提高数据库性能. mybaits提供一级缓存,和二级缓存. 一级缓存是SqlSession级别的缓存.在操作数据库时须要构造sqlSession对象,在对象中有一个数据结构(HashMa

Mybatis延迟加载和查询缓存

一.延迟加载 resultMap可以实现高级映射(使用association.collection实现一对一及一对多映射),association.collection具备延迟加载功能. 延迟加载:先从单表查询,需要时再从关联表去关联查询,大大提高数据库性能,因为查询单表要比关联查询多张表速度要快. 在mybatis核心配置文件中配置: lazyLoadingEnabled.aggressiveLazyLoading 设置项 描述 允许值 默认值 lazyLoadingEnabled 全局性设置

Mybatis学习总结(九)——查询缓存

一.什么是查询缓存 mybatis提供查询缓存,用于减轻数据压力,提高数据库性能.mybaits提供一级缓存和二级缓存. 1.一级缓存是sqlSession级别的缓存.在操作数据库时需要构造sqlSession对象,在对象中有一个数据结构(HashMap),用于存储缓存数据.不同的sqlSession之间的缓存区域(HashMap)是互不影响的. 2.二级缓存是mapper级别的缓存,多个sqlSession去操作同一个Mapper的sql语句,多个SqlSession可以公用二级缓存,二级缓存

mybatis 延迟加载 ,查询缓存

阅读目录 一.延迟加载 二.查询缓存 回到顶部 一.延迟加载 resultMap可以实现高级映射(使用association.collection实现一对一及一对多映射),association.collection具备延迟加载功能. 延迟加载:先从单表查询,需要时再从关联表去关联查询,大大提高数据库性能,因为查询单表要比关联查询多张表速度要快. 在mybatis核心配置文件中配置: lazyLoadingEnabled.aggressiveLazyLoading 设置项 描述 允许值 默认值

MyBatis入门第2天--高级映射与查询缓存

文档版本 开发工具 测试平台 工程名字 日期 作者 备注 V1.0 2016.06.28 lutianfei none mybatis框架执行过程: 1.配置mybatis的配置文件,SqlMapConfig.xml(名称不固定) 2.通过配置文件,加载mybatis运行环境,创建SqlSessionFactory会话工厂 SqlSessionFactory在实际使用时按单例方式. 3.通过SqlSessionFactory创建SqlSession SqlSession是一个面向用户接口(提供操