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()的存在,反而会清空整个二级缓存。

  • 相关阅读:
    【Java EE 学习 81】【CXF框架】【CXF整合Spring】
    【Java EE 学习 80 下】【调用WebService服务的四种方式】【WebService中的注解】
    【Java EE 学习 80 上】【WebService】
    【Java EE 学习 79 下】【动态SQL】【mybatis和spring的整合】
    【Java EE 学习 79 上】【mybatis 基本使用方法】
    【Java EE 学习 78 下】【数据采集系统第十天】【数据采集系统完成】
    【Java EE 学习 78 中】【数据采集系统第十天】【Spring远程调用】
    【Java EE 学习 78 上】【数据采集系统第十天】【Service使用Spring缓存模块】
    【Java EE 学习 77 下】【数据采集系统第九天】【使用spring实现答案水平分库】【未解决问题:分库查询问题】
    【Java EE 学习 77 上】【数据采集系统第九天】【通过AOP实现日志管理】【通过Spring石英调度动态生成日志表】【日志分表和查询】
  • 原文地址:https://www.cnblogs.com/chy18883701161/p/12158928.html
Copyright © 2011-2022 走看看