在一个Web项目中,查询数据库中的操做算是一个很是经常使用的操做,可是有些数据会被常常性的查询,而每一次都去数据库中查询这些重复的数据,会很消耗数据库的资源,同时使得查询效率也很低,而 MyBatis 中就经过缓存技术来解决这样的问题,也就是说:将一些常常查询,而且不常常改变的,以及数据的正确对最后的结果影响不大的数据,放置在一个缓存容器中,当用户再次查询这些数据的时候,就没必要再去数据库中查询,直接在缓存中提取就能够了java
注:缓存能够简单理解为存在于内存中的临时数据sql
MyBatis 提供了 一级缓存和二级缓存两种形式数据库
上面咱们总的讲了一级缓存的原理,如今梳理一下它细节缓存
以一个经过 id 查询用户的例子来讲微信
演示前,我把须要准备的一些类或者表现贴出来mybatis
CREATE TABLE USER ( `id` INT(11)NOT NULL AUTO_INCREMENT, `username` VARCHAR(32) NOT NULL COMMENT '用户名', `telephone` VARCHAR(11) NOT NULL COMMENT '手机', `birthday` DATETIME DEFAULT NULL COMMENT '生日', `gender` CHAR(1) DEFAULT NULL COMMENT '性别', `address` VARCHAR(256) DEFAULT NULL COMMENT '地址', PRIMARY KEY (`id`) ) ENGINE=INNODB DEFAULT CHARSET=utf8;
public class User implements Serializable { private Integer id; private String username; private String telephone; private Date birthday; private String gender; private String address; ...... 请补充 get set 方法 }
public interface UserMapper { /** * 根据id查询用户信息 * @param userId * @return */ User findById(Integer userId); }
<?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="cn.ideal.mapper.UserMapper"> <!-- 根据id查询用户 --> <select id="findById" parameterType="INT" resultType="user"> SELECT * FROM user where id = #{uid} </select> </mapper>
测试方法app
/** * 测试查询全部 */ @Test public void testFirstLevelCache() { User user1 = userMapper.findById(16); System.out.println(user1); User user2 = userMapper.findById(16); System.out.println(user2); System.out.println(user1 == user2); }
能够很明显的看到,当咱们在同一个 sqlSession的状况下,当咱们第一次查询 id 值为 16 的用户时,从数据库中确实查询到了数据,而第二次查询的时候,却没有任何日志的数据,而同时咱们能够看到,经过输出语句,看到两个对象是彻底相同的,这也就意味着,第二次查询不是从数据库查询出来的,而是从缓存中ide
经过上面的简单认识,咱们认识到一级缓存是基于同一个 SqlSession的,可是有时候因为方法封装的缘由,或者在查询完,SqlSession 对象会关闭,一级缓存就清空了,会致使没法从中获取内容测试
二级缓存的能够帮咱们解决一级缓存没法使用的状况,前面已经说过二级缓存是Mapper 级别的缓存,多个SqlSession类的实例对象加载同一个Mapper配置文件,并执行其中SQL配置的收,他们就共享同一个 Mapper 缓存,执行流程也与一级缓存基本是一致的ui
还依据刚开始准备的代码,咱们直接写出其测试代码,看看在不一样的 SqlSession 下,加载同一个Mapper的SQL是否会看到二级缓存的效果
@Test public void testSecondLevelCache() { SqlSession sqlSession1 = factory.openSession(); UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class); User user1 = mapper1.findById(16); sqlSession1.close(); SqlSession sqlSession2 = factory.openSession(); UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class); User user2 = mapper2.findById(16); sqlSession1.close(); System.out.println(user1 == user2); }
看完测试代码,咱们发现,SQL执行了两次,很显然,没有达到了咱们的指望,那么是哪里不对呢?
答案是,在MyBatis中一级缓存是默认开启的,而二级缓存则须要进行配置开启
要开启二级缓存,须要进行两个操做步骤
经过官网的文档,能够看到,默认值就是true,因此,不配置也是能够的,不过咱们仍是先给出来
<settings> <setting name="cacheEnabled" value="true"/> </settings>
只须要在文件中添加一个 cache标签就能够了,很是简单
<cache/>
还有一个须要注意的地方,那就是咱们最后作的判断 System.out.println(user1 == user2);
为何的到的结果倒是 false呢?
这是由于,在二级缓存中,存入的是值,而不是对象,当须要使用的时候,会建立出新的用户,而后将值传入,因此这里是不等的
不过使用二级缓存的时候,必定要谨慎,由于有时候不一样的namespace下的 SQL配置中可能缓存着相同的数据,如咱们上面的例子,UserMapper.xml 中有关于 user表的操做,可是若是在其余 Mmpper.xml 中仍然有针对 user 单表的操做,这会致使两方数据不同,若是在咱们 UserMapper.xml 进行了刷新缓存,可是另外一个Mapper.xml 中可能仍有效,因此可能会出现错误
若是文章中有什么不足,欢迎你们留言交流,感谢朋友们的支持!
若是能帮到你的话,那就来关注我吧!若是您更喜欢微信文章的阅读方式,能够关注个人公众号
在这里的咱们素不相识,却都在为了本身的梦而努力 ❤一个坚持推送原创开发技术文章的公众号:理想二旬不止