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 技术原理与实战》

  • 相关阅读:
    MSDN Magazine搞错了
    Visual Studio 2005中设置调试符号(Debug Symbols)
    BCB 6的问题
    吴裕雄天生自然Spring Boot使用Spring Data JPA实现人与身份证的一对一关系映射
    吴裕雄天生自然Spring BootSpring Data JPA
    吴裕雄天生自然Spring BootSpring Boot对JSP的支持
    吴裕雄天生自然Spring BootSpring Boot的异常统一处理
    吴裕雄天生自然Spring Boot使用Spring Data JPA实现Author与Article的一对多关系映射
    吴裕雄天生自然Spring Boot解决 Error creating bean with name 'entityManagerFactory' defined in class path resource
    吴裕雄天生自然Spring Boot@ExceptionHandler注解和@ControllerAdvice注解
  • 原文地址:https://www.cnblogs.com/qitian1/p/6461625.html
Copyright © 2011-2022 走看看