zoukankan      html  css  js  c++  java
  • Mybaits(13)缓存

    一、概述

      MyBatis像大多数持久层框架一样,也提供了缓存策略,通过缓存策略来减少数据库的查询次数,从而提高性能。 

      MyBatis分为一级缓存和二级缓存,同时也可以配置关于缓存的设置。

    二、一级缓存

     1.介绍

     一级缓存是在SqlSession上的缓存,只要 SqlSession 没有 flush 或 close,它就存在。默认情况下,也就是没有任何配置的情况下,MyBatis系统会开启一级缓存,也就是对于SqlSession层面的缓存,这个缓存不需要POJO对象序列化(实现java.io.Serializable接口)。

     2.测试,证明一级缓存的存在

     (1)编写测试类

    @Test
        public void  testCache() {
            // 5.创建Dao的代理对象
            roleDao = session.getMapper(IRoleDao.class);
            logger.info("第一次获取...");
            Role role = roleDao.getRole(1L);
            logger.info("第二次获取...");
            Role role1 = roleDao.getRole(1L);
    
        }

    (2)查看日志

    (3)分析

      虽然代码对同一对象进行了两次获取,但是实际上只有一条SQL,其原因是代码使用了同一个SqlSession对象获取数据,当一个SqlSession第一次通过Sql和参数获取对象后,它就将其缓存起来,如果下次Sql和参数都发生变化,并且缓存没有超时或者声明需要刷新时,它就会从缓存中获取数据,而不是通过Sql获取了。

       当一级缓存是 SqlSession 范围的缓存,当调用 SqlSession 的修改,添加,删除,commit(),close()等会清空一级缓存。如果 sqlSession 去执行 commit 操作(执行插入、更新、删除),清空 SqlSession 中的一级缓存,这样做的目的为了让缓存中存储的是最新的信息,避免脏读。

    (4)一级缓存清空测试

    清空缓存

    @Test
        public void  testClearCache() {
            // 5.创建Dao的代理对象
            roleDao = session.getMapper(IRoleDao.class);
            logger.info("第一次获取...");
            Role role = roleDao.getRole(1L);
            //此方法也可以清空缓存
            session.clearCache();
            logger.info("第二次获取...");
            Role role1 = roleDao.getRole(1L);
            logger.info(role==role1);
    
        }

     从日志可以看出sql执行了两次,最后执行结果为false,缓存被清空。对于不同的SqlSession对象是不能共享的,为了使SqlSession对象之间能共享相同的缓存,有时需要开启二级缓存,开启二级缓存很简单,只需要在映射文件上加入代码:<cache/>,这个时候MyBatis会序列化和反序列对应的实体类(POJO),也就要求POJO是一个可序列化的对象,那么必须实现java.io.Serializable接口。

    二、二级缓存

    1、概念

      指的是MyBatis中的SqlSessionFactory对象的缓存。由于同一个SqlSessionFactory对象的创建的SQLSession共享其内存。

      二级缓存是 mapper 映射级别的缓存,多个 SqlSession 去操作同一个 Mapper 映射的 sql 语句,多个SqlSession 可以共用二级缓存,二级缓存是跨 SqlSession 

    2、二级缓存测试

    (1)二级缓存开与关

      在 SqlMapConfig.xml 文件开启二级缓存 
    <settings>
            <setting name="lazyLoadingEnabled" value="true" />
            <setting name="aggressiveLazyLoading" value="false" />
            <!-- 开启二级缓存 -->
            <setting name="cacheEnabled" value="true"/>
        </settings>
      因为 cacheEnabled 的取值默认就为 true,所以这一步可以省略不配置。为 true 代表开启二级缓存;为
    false 代表不开启二级缓存。 

    (2)配置相关的 Mapper 映射文件

      标签表示当前这个 mapper 映射将使用二级缓存,区分的标准就看 mapper 的 namespace 值。 
    <?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.xhbjava.dao.IUserDao">
        <cache></cache>
        <resultMap type="com.xhbjava.domain.User" id="userMapper">
    
            <id column="id" property="id" />
            <result column="user_name" property="userName" />
            <result column="real_name" property="realName" />
            <result column="sex" property="sex"
                typeHandler="com.xhbjava.typeHandler.SexTypeHandler" />
            <result column="mobile" property="moble" />
            <result column="email" property="email" />
            <result column="position" property="position" />
            <result column="note" property="note" />
            <collection property="roleList" column="id"
                fetchType="lazy" select="com.xhbjava.dao.IRoleDao.findRoleByUserId" />
        </resultMap>
        <select id="getUser" parameterType="long" resultMap="userMapper">
            select id,
            user_name, real_name, sex, moble, email, note from t_user where
            id
            =#{id}
        </select>
        <select id="findUserByRoleId" parameterType="long"
            resultMap="userMapper">
            select u.id, u.user_name, u.real_name, u.sex, u.moble,
            u.email, u.note
            from
            t_user u , t_user_role ur where u.id = ur.user_id
            and ur.role_id =#{roleId}
        </select>
    
    </mapper>

    (3)配置 statement 上面的 useCache 属性

    <select id="getUser" parameterType="long" resultMap="userMapper" useCache="true">
            select id,
            user_name, real_name, sex, moble, email, note from t_user where
            id
            =#{id}
        </select>

      将 UserDao.xml 映射文件中的<select>标签中设置 useCache=”true”代表当前这个 statement 要使用二级缓存,如果不使用二级缓存可以设置为 false。

      注意:针对每次查询都需要最新的数据 sql,要设置成 useCache=false,禁用二级缓存。

    (4)编写测试类进行测试

    @Test
    	public void  testSecondLevelCache() {
    		// 5.创建Dao的代理对象
    		 session = factory.openSession(true);
    	     userDao = session.getMapper(IUserDao.class);
    		logger.info("第一次获取...");
    		User user = userDao.getUser(1L);
    		//一级缓存消失
    		session.close();
    		logger.info("第二次获取...");
    		// 5.创建Dao的代理对象
    		session11 = factory.openSession(true);
    		userDao1 = session11.getMapper(IUserDao.class);
    		User user1 = userDao1.getUser(1L);
    		logger.info(user==user1);
    
    	}

      经过上面的测试,我们发现执行了两次查询,并且在执行第一次查询后,我们关闭了一级缓存,再去执行第二次查询时,我们发现并没有对数据库发出 sql 语句,所以此时的数据就只能是来自于我们所说的二级缓存。 

    注意:使用二级缓存,缓存的类一定要实现 java.io.Serializable 接口,这样可以使用序列化方式来保存对象。 

    三、缓存配置项、自定义和引用

    1.cache元素配置项:

    属性 说明 取值 备注
    blocking 是否使用阻塞性缓存,在读写时会加入JNI的锁进行操作 true|false,默认false 保证读写安全性,但加锁后性能不佳
    readOnly 缓存内容是否只读 true|false,默认false 如果是只读,不会因为多个线程读写造成不一致
    eviction

    缓存策略:

    LRU最近最少使用:移除最长时间不被使用的对象

    FIFO先进先出:按照对象进入缓存的顺序移除

    SOFT软引用:移除基于垃圾回收器状态和软引用规则对象

    WEAK弱引用:积极移除基于垃圾收集器状态和弱引用规则对象

    默认false  
    flushInterval

    这是一个整数,以毫秒为单位,比如1分钟刷新一次,则配置60000.

    默认为null,也就是没有刷新时间,只有执行update,inset和delete

    时才会刷新。

    正整数

    超过设置的整数后缓存消失,不再读取缓存,而是执行SQL

    取回数据。

    type 自定义缓存类。要求实现org.apache.ibatis.cache.Cache 用于自定义缓存类  
    size 缓存对象个数 正整数。默认是1024  

    2.自定义缓存类

      在实际工作中,我们可以使用Redis,MongoDB或者其他常用的缓存,假设我们在存在Redis的一个缓存实现类RedisCache,我们可以这样配置:

    <cache type="XXX.XX.RedisCache">

    <property name="host" value="localhost" />

    </cache>

    这样配置后,MyBatis就会启用缓存,同时调用setHost(String host)方法,去设置配置的内容。

    上面的配置时通用的,对于一些语句也需要自定义,比如一些查询不想让它们进行缓存,我们可以如下配置:

    <select ... flushCache="false" userCache="true">

    <insert ... flushCache="true" >

    <update... flushCache="true" >

    <delete ... flushCache="true" >

    以上是默认配置,我们可以根据需要去修改。flashCache代表是否刷新缓存,对于select、insert、update和delete都是有效的。useCache是select特有的,代表是否启用缓存。

    这里都是在一个映射配置文件中配置的,比如IUserDao.xml,其他的映射配置文件不能使用,如果其他映射配置文件需要使用同样的配置,则可以引用缓存的配置:

    <cache-ref namespace="XXX.XX.IUserDao"/>这样就可以引用对应映射文件的cache元素的配置了。

    UserDao.xml 映射文件中的
  • 相关阅读:
    MFC OnOk(),OnCancel(),OnClose(),OnDestroy()的区别总结
    MFC中的Invalidate、OnDraw、OnPaint函数的作用
    MFC中和定时器使用
    SwapBuffers的等待,虚伪的FPS(转)
    OpenGl常用函数说明
    Win7_Ultimate + VS2010 + openGL_MFC单文档应用开发框架搭建步骤
    OpenGL模型视图变换、投影变换、视口变换的理解
    不同电脑的开机启动项
    第一百二十三节,JavaScript错误处理与调试
    第一百二十二节,JavaScript表单处理
  • 原文地址:https://www.cnblogs.com/xhbJava/p/12390119.html
Copyright © 2011-2022 走看看