zoukankan      html  css  js  c++  java
  • mybatis中的缓存问题

    关于mybatis基础我们前面几篇博客已经介绍了很多了,今天我们来说一个简单的问题,那就是mybatis中的缓存问题。mybatis本身对缓存提供了支持,但是如果我们没有进行任何配置,那么默认情况下系统只开启了一级缓存,一级缓存就是同一个SqlSession执行的相同查询是会进行缓存的,OK,那么今天我们就来看看这些缓存,并简单验证下。

    系统默认开启了一级缓存

    这个缓存系统默认情况下是开启的,当我们获取到一个SqlSession对象之后,如果调用SqlSession中的同一个方法查询同一条数据,那么第二次查询将不会去数据库中查询,因为第一次查询有缓存,直接调用缓存数据即可,除非缓存超时或者我们明确声明数据要刷新,否则都是直接调用缓存数据。OK,我们来看一个简单的案例。
    查询代码如下:

    SqlSession sqlSession = null;
            try {
                sqlSession = DBUtils.openSqlSession();
                UserMapper mapper = sqlSession.getMapper(UserMapper.class);
                //查询同一条数据时会缓存
                User user = mapper.getUser(1l);
                User user2 = mapper.getUser(1l);
                System.out.println(user.toString());
                System.out.println(user2.toString());
                sqlSession.commit();
            } catch (Exception e) {
                System.err.println(e.getMessage());
                sqlSession.rollback();
            } finally {
                if (sqlSession != null) {
                    sqlSession.close();
                }
            }

    我们来看看日志:
    这里写图片描述
    小伙伴们看到,我这里执行了两次查询,但实际上只执行了一次SQL语句。

    自己配置二级缓存

    上面的缓存是由系统默认配置的,这个有一定的局限性,就是只能在同一个SqlSession中有效,脱离了同一个SqlSession就没法使用这个缓存了,有的时候我们可能希望能够跨SqlSession进行数据缓存。那么这个时候需要我们进行手动开启二级缓存。
    二级缓存的开启方式其实很简单,只需要我们在userMapper.xml中配置<cache/>节点即可。如下:

    <?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="org.sang.db.UserMapper">
        <cache/>
        <select id="getUser" resultType="org.sang.bean.User" parameterType="Long">
            select * from user where id = #{id}
        </select>
        <insert id="insertUser" parameterType="org.sang.bean.User">
            INSERT INTO user(username,password,address) VALUES (#{username},#{password},#{address})
        </insert>
        <delete id="deleteUser" parameterType="Long">
            DELETE FROM user where id=#{id}
        </delete>
        <select id="getAll" resultType="u">
            SELECT * from user
        </select>
    </mapper>

    这样简单配置之后,二级缓存就算开启了,这样的配置中,许多东西都是默认的,比如所有的select语句都会被缓存,所有的delete、insert和update则都会将缓存刷新,还比如缓存将使用LRU算法进行内存回收等。那么这些东西如果需要配置的话,我们可以按如下方式进行配置:
    <cache eviction="LRU" flushInterval="20000" size="1024" readOnly="true"/>,这里的eviction表示缓存策略,除了LRU之外还有先进先出(FIFO)、软引用(SOFT)、弱引用(WEAK)等,flushInterval则表示刷新时间,表示缓存的对象个数,readOnly为true则表示缓存只可以读取不可以修改。
    OK,做了如上配置之后还不够,开启二级缓存还要求我们的实体类可以序列化,实现Serializable接口即可,如下:

    public class User implements Serializable{
        private Long id;
        private String username;
        private String password;
        private String address;
    
        ...
    
    }

    如此之后,我们的二级缓存就算成功开启了,OK,我么来测试下:

    SqlSession sqlSession = null;
            SqlSession sqlSession2 = null;
            try {
                sqlSession = DBUtils.openSqlSession();
                UserMapper mapper = sqlSession.getMapper(UserMapper.class);
                User user = mapper.getUser(1l);
                System.out.println(user.toString());
                sqlSession.commit();
                sqlSession2 = DBUtils.openSqlSession();
                UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class);
                User user2 = mapper2.getUser(1l);
                System.out.println(user2.toString());
                sqlSession2.commit();
            } catch (Exception e) {
                System.err.println(e.getMessage());
                sqlSession.rollback();
                sqlSession2.rollback();
            } finally {
                if (sqlSession != null) {
                    sqlSession.close();
                }
                if (sqlSession2 != null) {
                    sqlSession2.close();
                }
            }

    打印日志如下:
    这里写图片描述
    OK,小伙伴们看到SQL语句实际上只执行了一次。

    OK,以上就是对mybatis中缓存的一个简单介绍。

    本文案例下载:
    本文案例GitHub地址https://github.com/lenve/JavaEETest/tree/master/Test27-mybatis8

    参考资料:
    《深入浅出MyBatis 技术原理与实战》

    关注公众号【江南一点雨】,专注于 Spring Boot+微服务以及前后端分离等全栈技术,定期视频教程分享,关注后回复 Java ,领取松哥为你精心准备的 Java 干货!

  • 相关阅读:
    基于硬件的毕业设计论文的书写
    C语言程序设计课程总结
    嵌入式程序设计第三周成绩汇总
    C第十八次课
    2016-4班平时成绩第9周排名和汇总
    2016-3班平时成绩第9周汇总和排名
    第十七次课大纲
    第十六次课大纲
    2020-02-28
    2020-02-27
  • 原文地址:https://www.cnblogs.com/lenve/p/7530969.html
Copyright © 2011-2022 走看看