zoukankan      html  css  js  c++  java
  • MyBatis 查询结果的缓存

    MyBatis的缓存指的是缓存查询结果,当以后使用相同的sql语句、传入相同的参数进行查询时,可直接从mybatis本地缓存中获取查询结果,而不必查询数据库。

    mybatis的缓存包括一级缓存、二级缓存,一级缓存默认是开启的,二级缓存默认是关闭的。

    一级缓存:

    SqlSession级别,在SqlSession中有一个Map,key是由sql语句、参数等信息组成的唯一值,value是查询出来的结果对象。

    二级缓存:

    mapper级别,同一个namespace下的mapper,有一个Map。

    二级缓存可以使这些sqlSession做到查询结果共享。


     

    一级缓存

    一级缓存默认是开启的。

            User user1 = mapper.queryUserById(1);
            User user2 = mapper.queryUserById(1);

    第一次查询时,就将查询结果放到一级缓存中。

    如果后续使用的sql语句相同、传入的实参也相同,则结果对象也会相同,直接从一级缓存中获取结果对象,不再查询数据库。

            User user1 = mapper.queryUserById(1);
            sqlSession.commit();
            User user2 = mapper.queryUserById(1);

    如果此sqlSession调用了commit()方法,会自动清空此sqlSession的一级缓存。

    因为使用commit(),会将修改提交到数据库,下一次相同的查询,查询结果可能变了,之前的一级缓存不能再用,所以会自动清空。

         User user1 = mapper.queryUserById(1);
    
            HashMap<String, Object> map = new HashMap<>();
            map.put("username", "张三");
            map.put("id", 1);
            mapper.updateUser(map);
    
            User user2 = mapper.queryUserById(1);

    事实上,只要此sqlSession调用了<update>、<insert>、<delete>这些会修改数据库的元素,就会清空此sqlSession的一级缓存,不管有没有使用commit()提交。


    二级缓存

         SqlSession sqlSession1 = MyBatisUtils.getSqlSession();
            UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class);
            User user1 = mapper1.queryUserById(1);
            System.out.println(user1);
    
            SqlSession sqlSession2 = MyBatisUtils.getSqlSession();
            UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class);
            User user2 = mapper2.queryUserById(1);
            System.out.println(user2);

    不使用二级缓存,会执行2次查询。

    二级缓存的使用步骤,此处以UserMapper为例:

    (1)pojo类要是可序列化的

    public class User implements Serializable {
        //......
    }

    (2)在mybatis全局配置文件中开启二级缓存

    <settings>
            <setting name="logImpl" value="LOG4J"/>
            <setting name="cacheEnabled" value="true"/>
    </settings>

    二级缓存默认是关闭的,需要手动开启。

    (3)在mapper映射文件中指定二级缓存的实现方式,必须显式指定

    <?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.chy.mapper.UserMapper">
        <cache />
        <select id="queryUserById" parameterType="integer" resultType="user">
            SELECT * FROM user_tb WHERE id=#{id}
         </select>
        <update id="updateUser" parameterType="hashmap">
            UPDATE user_tb SET username=#{username} WHERE id=#{id}
        </update>
    </mapper>

    完整写法:

    <cache type="perpetualCache" />

    type指定二级缓存的实现方式,缺省type时默认使用mybatis自带的perpetualCache。

    (4)需要调用close()关闭sqlSession,才会将此sqlSession的查询结果(一级缓存)写入到二级缓存中

         SqlSession sqlSession1 = MyBatisUtils.getSqlSession();
            UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class);
            User user1 = mapper1.queryUserById(1);
            System.out.println(user1);
            sqlSession1.close();
    
            SqlSession sqlSession2 = MyBatisUtils.getSqlSession();
            UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class);
            User user2 = mapper2.queryUserById(1);
            System.out.println(user2);

    只执行1次查询。后续使用相同sql语句、传入相同的实参进行查询时,直接从二级缓存中获取结果对象。

    提交修改时,会清空整个二级缓存:

         SqlSession sqlSession1 = MyBatisUtils.getSqlSession();
            UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class);
            User user1 = mapper1.queryUserById(1);
            System.out.println(user1);
    
            HashMap<String, Object> hashMap = new HashMap<>();
            hashMap.put("username", "j");
            hashMap.put("id", 1);
            mapper1.updateUser(hashMap);
            sqlSession1.commit();
    
            SqlSession sqlSession2 = MyBatisUtils.getSqlSession();
            UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class);
            User user2 = mapper2.queryUserById(2);
            System.out.println(user2);

    只写了commit()、实际没有调用<insert> | <update> | <delete>,不会清空二级缓存,反而会将之前查询结果写入到二级缓存。

    写了commit()、有调用<insert> | <update> | <delete>,会清空整个二级缓存。

    先后调用commit()、close(),不会写入二级缓存,因为commit()的存在,反而会清空整个二级缓存。

  • 相关阅读:
    [原创]如何在Windows下安装Bugfree2.0.0.1
    [原创]网站性能优化利器之一"google page speed"
    [原创]下一代Web 应用程序安全性测试工具HP WebInspect简介
    [原创]微软软件项目管理Team Foundation Server之测试人员
    [原创]Yeepay网站安全测试漏洞之跨站脚本注入
    [原创]软件测试过程改进的内容和注意事项
    [原创]快钱99bill网站安全性测试漏洞之“跨站式脚本注入”
    马化腾内部讲座:让产品自己召唤人
    [转贴]可用性测试
    [原创]浅谈缺陷分析的意义和方法
  • 原文地址:https://www.cnblogs.com/chy18883701161/p/12158928.html
Copyright © 2011-2022 走看看