php mysql开发的网站,网络做推广广告公司,shopnc,html网站建设代码MyBatis缓存引言在一个Web项目中#xff0c;查询数据库中的操作算是一个非常常用的操作#xff0c;但是有些数据会被经常性的查询#xff0c;而每一次都去数据库中查询这些重复的数据#xff0c;会很消耗数据库的资源#xff0c;同时使得查询效率也很低#xff0c;而 MyB…MyBatis缓存引言在一个Web项目中查询数据库中的操作算是一个非常常用的操作但是有些数据会被经常性的查询而每一次都去数据库中查询这些重复的数据会很消耗数据库的资源同时使得查询效率也很低而 MyBatis 中就通过缓存技术来解决这样的问题也就是说将一些经常查询并且不经常改变的以及数据的正确对最后的结果影响不大的数据放置在一个缓存容器中当用户再次查询这些数据的时候就不必再去数据库中查询直接在缓存中提取就可以了注缓存可以简单理解为存在于内存中的临时数据MyBatis 提供了 一级缓存和二级缓存两种形式一级缓存 它是 SqlSession 级别的缓存SqlSession 类的实例对象中提供了一个 HashMap 的结构可以用于存储缓存数据当我们再次查询同一数据的时候MyBatis 会先去 SqlSession 中查询有的话就直接调用二级缓存 是Mapper 级别的缓存也就是说如果多个 SqlSession 类的实例去操作同一个Mapper配置文件中的SQL这些实例对象可以共用二级缓存一级缓存(1) 基本阐述上面我们总的讲了一级缓存的原理现在梳理一下它细节以一个通过 id 查询用户的例子来说第一次查询 id 为某个值的用户信息时先去 SqlSesion 的一级缓存中去寻找如果找到了就直接用如果没有找到就去数据库中去查然后将查到的内容存到一级缓存区域但是如果在下一次操作中执行了 commit 操作也就是执行了增删改的操作一级缓存区域内的内容会被清空这是为了保证缓存中的数据的有效性避免脏读的产生(2) 程序演示演示前我把需要准备的一些类或者表现贴出来User表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)) ENGINEINNODB DEFAULT CHARSETutf8;User实体类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 方法}UserMapper接口public interface UserMapper { /** * 根据id查询用户信息 * param userId * return */ User findById(Integer userId);}UserMapper.xml?xml version1.0 encodingUTF-8? SELECT * FROM user where id #{uid} 测试方法/*** 测试查询所有*/Testpublic 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 的用户时从数据库中确实查询到了数据而第二次查询的时候却没有任何日志的数据而同时我们可以看到通过输出语句看到两个对象是完全相同的这也就意味着第二次查询不是从数据库查询出来的而是从缓存中二级缓存(1) 基本阐述通过上面的简单认识我们认识到一级缓存是基于同一个 SqlSession的但是有时候由于方法封装的原因或者在查询完SqlSession 对象会关闭一级缓存就清空了会导致无法从中获取内容二级缓存的可以帮我们解决一级缓存无法使用的情况前面已经说过二级缓存是Mapper 级别的缓存多个SqlSession类的实例对象加载同一个Mapper配置文件并执行其中SQL配置的收他们就共享同一个 Mapper 缓存执行流程也与一级缓存基本是一致的查询时先去Mapper缓存区去找这个值如果找不到就去数据库查然后将查询到的结果存储到缓存中等下次使用当某个 SqlSession 类的实例对象执行了增删改操作时二级缓存会被清空还依据刚开始准备的代码我们直接写出其测试代码看看在不同的 SqlSession 下加载同一个Mapper的SQL是否会看到二级缓存的效果(2) 程序演示测试代码Testpublic 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中一级缓存是默认开启的而二级缓存则需要进行配置开启要开启二级缓存需要进行两个操作步骤①在总配置文件 SqlMapConfig.xml 中配置 setting属性②在SQL映射文件中开启二级缓存通过官网的文档可以看到默认值就是true所以不配置也是可以的不过我们还是先给出来修改 SqlMapConfig.xml修改 UserMapper.xml只需要在文件中添加一个 cache标签就可以了非常简单执行效果还有一个需要注意的地方那就是我们最后做的判断 System.out.println(user1 user2); 为什么的到的结果却是 false呢这是因为在二级缓存中存入的是值而不是对象当需要使用的时候会创建出新的用户然后将值传入所以这里是不等的不过使用二级缓存的时候一定要谨慎因为有时候不同的namespace下的 SQL配置中可能缓存着相同的数据如我们上面的例子UserMapper.xml 中有关于 user表的操作但是如果在其他 Mmpper.xml 中仍然有针对 user 单表的操作这会导致两方数据不一样如果在我们 UserMapper.xml 进行了刷新缓存但是另一个Mapper.xml 中可能仍有效所以可能会出现错误