700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > 【MyBatis框架】查询缓存-二级缓存原理

【MyBatis框架】查询缓存-二级缓存原理

时间:2024-03-10 13:41:31

相关推荐

【MyBatis框架】查询缓存-二级缓存原理

二级缓存原理

1.原理

首先看图

首先开启mybatis的二级缓存。

sqlSession1去查询用户id为1的用户信息,查询到用户信息会将查询数据存储到二级缓存中。

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

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

二级缓存与一级缓存区别,二级缓存的范围更大,多个sqlSession可以共享一个UserMapper的二级缓存区域。

UserMapper有一个二级缓存区域(按namespace分) ,其它mapper也有自己的二级缓存区域(按namespace分)。

每一个namespace的mapper都有一个二缓存区域,两个mapper的namespace如果相同,这两个mapper执行sql查询到数据将存在相同 的二级缓存区域中。

2.开启二级缓存

mybaits的二级缓存是mapper范围级别,除了在SqlMapConfig.xml设置二级缓存的总开关,还要在具体的mapper.xml中开启二级缓存。

在核心配置文件SqlMapConfig.xml中加入

[html]view plaincopy<settingname="cacheEnabled"value="true"/>

描述允许值默认值

cacheEnabled 对在此配置文件下的所有cache 进行全局性开/关设置。true falsetrue

在UserMapper.xml中开启二缓存,UserMapper.xml下的sql执行完成会存储到它的缓存区域(HashMap)。

<!-- 开启本Mapper的namespace下的二级缓存 -->

<cache/>

3.调用pojo类实现序列化接口

[java]view plaincopypublicclassUserimplementsSerializable{privateintid;privateStringusername;//用户姓名privateStringsex;//性别privateDatebirthday;//生日privateStringaddress;//地址//...}

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

4.测试方法

先测试二级缓存的存在

[java]view plaincopy //测试二级缓存@TestpublicvoidtestCache2()throwsException{SqlSessionsqlSession1=sqlSessionFactory.openSession();SqlSessionsqlSession2=sqlSessionFactory.openSession();SqlSessionsqlSession3=sqlSessionFactory.openSession();UserMapperuserMapper1=sqlSession1.getMapper(UserMapper.class);//创建代理对象//下边查询使用一个SqlSession//第一次发起请求,查询id为1的用户Useruser1=userMapper1.findUserById(1);System.out.println(user1.getUsername());//不关闭SqlSession无法写进二级缓存区域中sqlSession1.close();UserMapperuserMapper2=sqlSession2.getMapper(UserMapper.class);//创建代理对象//第二次发起请求,查询id为1的用户Useruser2=userMapper2.findUserById(1);System.out.println(user2.getUsername());sqlSession2.close();}

测试结果和输出日志:

[plain]view plaincopy DEBUG[main]-CacheHitRatio[cn.edu.hpu.mybatis.mapper.UserMapper]:0.0DEBUG[main]-OpeningJDBCConnectionDEBUG[main]-Createdconnection26255574.DEBUG[main]-SettingautocommittofalseonJDBCConnection[com.mysql.jdbc.Connection@190a0d6]DEBUG[main]-==>Preparing:SELECT*FROMUSERWHEREid=?DEBUG[main]-==>Parameters:1(Integer)DEBUG[main]-<==Total:1张三DEBUG[main]-ResettingautocommittotrueonJDBCConnection[com.mysql.jdbc.Connection@190a0d6]DEBUG[main]-ClosingJDBCConnection[com.mysql.jdbc.Connection@190a0d6]DEBUG[main]-Returnedconnection26255574topool.DEBUG[main]-CacheHitRatio[cn.edu.hpu.mybatis.mapper.UserMapper]:0.5张三

我们可以发现,日志输出中有一句我们之前没有见过,是:

Cache Hit Ratio [cn.edu.hpu.mybatis.mapper.UserMapper]: 0.0

这句的意思是缓存命中率为0.0,说明第一次是在缓存中找,可是没找到

DEBUG [main] - Cache Hit Ratio [cn.edu.hpu.mybatis.mapper.UserMapper]: 0.5

这句的意思是缓存命中率为0.5,说明第一次是在缓存中找,可是没找到,第二次找到了。

这个测试证明了二级缓存的存在

下面证明第三方sqlSession执行增删改会清空缓存的事实:

[java]view plaincopy //测试二级缓存@TestpublicvoidtestCache2()throwsException{SqlSessionsqlSession1=sqlSessionFactory.openSession();SqlSessionsqlSession2=sqlSessionFactory.openSession();SqlSessionsqlSession3=sqlSessionFactory.openSession();UserMapperuserMapper1=sqlSession1.getMapper(UserMapper.class);//创建代理对象//下边查询使用一个SqlSession//第一次发起请求,查询id为1的用户Useruser1=userMapper1.findUserById(1);System.out.println(user1.getUsername());//不关闭SqlSession无法写进二级缓存区域中sqlSession1.close();UserMapperuserMapper3=sqlSession3.getMapper(UserMapper.class);//创建代理对象Useruser=userMapper3.findUserById(1);user.setUsername("张明明");userMapper3.updateUser(user);//执行提交,清空UserMapper二级缓存mit();sqlSession3.close();UserMapperuserMapper2=sqlSession2.getMapper(UserMapper.class);//创建代理对象//第二次发起请求,查询id为1的用户Useruser2=userMapper2.findUserById(1);System.out.println(user2.getUsername());sqlSession2.close();}

输出结果和日志信息:

[plain]view plaincopy DEBUG[main]-CacheHitRatio[cn.edu.hpu.mybatis.mapper.UserMapper]:0.0DEBUG[main]-OpeningJDBCConnectionDEBUG[main]-Createdconnection189219.DEBUG[main]-SettingautocommittofalseonJDBCConnection[com.mysql.jdbc.Connection@2e323]DEBUG[main]-==>Preparing:SELECT*FROMUSERWHEREid=?DEBUG[main]-==>Parameters:1(Integer)DEBUG[main]-<==Total:1张三DEBUG[main]-ResettingautocommittotrueonJDBCConnection[com.mysql.jdbc.Connection@2e323]DEBUG[main]-ClosingJDBCConnection[com.mysql.jdbc.Connection@2e323]DEBUG[main]-Returnedconnection189219topool.DEBUG[main]-CacheHitRatio[cn.edu.hpu.mybatis.mapper.UserMapper]:0.5DEBUG[main]-OpeningJDBCConnectionDEBUG[main]-Checkedoutconnection189219frompool.DEBUG[main]-SettingautocommittofalseonJDBCConnection[com.mysql.jdbc.Connection@2e323]DEBUG[main]-==>Preparing:updateusersetusername=?,birthday=?,sex=?,address=?whereid=?DEBUG[main]-==>Parameters:张明明(String),-06-07(Date),男(String),河南焦作(String),1(Integer)DEBUG[main]-<==Updates:1DEBUG[main]-CommittingJDBCConnection[com.mysql.jdbc.Connection@2e323]DEBUG[main]-ResettingautocommittotrueonJDBCConnection[com.mysql.jdbc.Connection@2e323]DEBUG[main]-ClosingJDBCConnection[com.mysql.jdbc.Connection@2e323]DEBUG[main]-Returnedconnection189219topool.DEBUG[main]-CacheHitRatio[cn.edu.hpu.mybatis.mapper.UserMapper]:0.3333333333333333DEBUG[main]-OpeningJDBCConnectionDEBUG[main]-Checkedoutconnection189219frompool.DEBUG[main]-SettingautocommittofalseonJDBCConnection[com.mysql.jdbc.Connection@2e323]DEBUG[main]-==>Preparing:SELECT*FROMUSERWHEREid=?DEBUG[main]-==>Parameters:1(Integer)DEBUG[main]-<==Total:1张明明DEBUG[main]-ResettingautocommittotrueonJDBCConnection[com.mysql.jdbc.Connection@2e323]DEBUG[main]-ClosingJDBCConnection[com.mysql.jdbc.Connection@2e323]DEBUG[main]-Returnedconnection189219topool.

发现第二次再去查1号用户的时候,又再一次查询了数据库,查到了最新的数据"张明明"。

二级缓存远远没有那么简单,他还有一些配置的参数。

5.useCache配置

在statement中设置useCache=false可以禁用当前select语句的二级缓存,即每次查询都会发出sql去查询,默认情况是true,即该sql使用二级缓存。

[html]view plaincopy<selectid="findOrderListResultMap"resultMap="ordersUserMap"useCache="false">

总结:针对每次查询都需要最新的数据sql,要设置成useCache=false,禁用二级缓存。

6.刷新缓存(就是清空缓存)

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

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

如下:

[html]view plaincopy<insertid="insertUser"parameterType="cn.itcast.mybatis.po.User"flushCache="true">

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

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。