Mybatis的二级缓存

102 阅读3分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

1.二级缓存

  1. 为什么需要缓存

    拉高程序的性能

  2. 什么样的数据需要缓存

    很少被修改或根本不改的数据

    业务场景比如:耗时较高的统计分析sql、电话账单查询sql等

  3. ehcache是什么

    Ehcache 是现在最流行的纯Java开源缓存框架,配置简单、结构清晰、功能强大

    注1:本章介绍的是2.X版本,3.x的版本和2.x的版本API差异比较大

  4. ehcache的特点

4.1 够快

  Ehcache的发行有一段时长了,经过几年的努力和不计其数的性能测试,Ehcache终被设计于large, high concurrency systems.

4.2 够简单

  开发者提供的接口非常简单明了,从Ehcache的搭建到运用运行仅仅需要的是你宝贵的几分钟。其实很多开发者都不知道自己用在用Ehcache,Ehcache被广泛的运用于其他的开源项目

4.3 够袖珍

  关于这点的特性,官方给了一个很可爱的名字small foot print ,一般Ehcache的发布版本不会到2M,V 2.2.3668KB。

4.4 够轻量

  核心程序仅仅依赖slf4j这一个包,没有之一!

4.5 好扩展

  Ehcache提供了对大数据的内存和硬盘的存储,最近版本允许多实例、保存对象高灵活性、提供LRU、LFU、FIFO淘汰算法,基础属性支持热配置、支持的插件多

4.6 监听器

  缓存管理器监听器 (CacheManagerListener)和 缓存监听器(CacheEvenListener),做一些统计或数据一致性广播挺好用的

4.7 分布式缓存

  从Ehcache 1.2开始,支持高性能的分布式缓存,兼具灵活性和扩展性

3. ehcache的使用

3.1 导入相关依赖

3.2 核心接口

  CacheManager:缓存管理器

  Cache:缓存对象,缓存管理器内可以放置若干cache,存放数据的实质,所有cache都实现了Ehcache接口

  Element:单条缓存数据的组成单位
  

它指的是Mybatis中SqlsessionFactory对象的缓存,由同一个SqlSessionFactory对象创建,其中创建的SqlSession共享其缓存

二级缓存的使用步骤:

  • 1.让Mybatis框架支持二级缓存(在SqlMapConfig.xml中配置)
  • 2.让当前的映射文件支持二级缓存(在IUserDao.xml中配置)
  • 3.让当前的操作支持二级缓存(在select标签中配置)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>

    <!--配置properties文件 可以在标签内部配置数据库的信息,也可以通过属性引用外部配置信息
    resource属性:用于指定配置文件的位置,是按照类路径的写法来写平且必须存在与类路径下
    -->
    <properties resource="jdbcConfig.properties">
    </properties>
    <!--配置参数延迟加载-->
    <settings>
        <!--开启mybatis支持延迟加载-->
        <setting name="cacheEnabled" value="true"/><!--开启二级缓存-->
        <setting name="lazyLoadingEnabled" value="true"/>
        <setting name="aggressiveLazyLoading" value="false"/>
    </settings>
    <!--配置环境-->
    <environments default="mysql">
        <!--配置mysql环境-->
        <environment id="mysql">
            <!--配置事物类型-->
            <transactionManager type="JDBC"></transactionManager>
            <dataSource type="POOLED">
                <!--配置连接数据库的4个信息-->
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>
    <!--指定映射配置文件的位置,映射配置文件指的是每个到独立的配置文件-->
    <!--<mappers>
        <mapper resource="com/mybatisD/dao/IUserDao.xml"/>
     <mapper resource="com/mybatisD/dao/IAccountDao.xml"/>
    </mappers>-->
    <!--如果要是用注解来配置的话,此处应该使用class属性指定被注解的dao全限定类名-->
    <!--<mappers>
        <mapper class="com.mybatisD.dao.IUserDao"/>
    </mappers>-->
    <mappers >
        <!--package标签用于指定doa接口所在的包,当指定了之后就不需要在写mapper以及resource或者class了-->
        <package name="com.mybatisD.dao"/>
    </mappers>
</configuration>

配置IUserDao.xml配置开启二级缓存

<?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.mybatisD.dao.IUserDao">
    <!--开启User支持二级缓存-->
    <cache/>
    <!--配置查询所有-->
    <select id="findAll" resultType="com.mybatisD.domain.User" useCache="true">
       select * from user
    </select>
    <!--根据ID查询用户-->
    <select id="findById" parameterType="INT" resultType="com.mybatisD.domain.User">
        select * from user where id=#{userid}
    </select>
   
</mapper>

测试方法

package com.mybatisJ.test;

import com.mybatisD.dao.IUserDao;
import com.mybatisD.domain.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.InputStream;
import java.util.Date;

import com.mybatisD.dao.IAccountDao;
import com.mybatisD.dao.IUserDao;
import com.mybatisD.domain.Account;
import com.mybatisD.domain.AccountUser;
import com.mybatisD.domain.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.InputStream;
import java.util.Date;
import java.util.List;
/**
 * @author :程序员徐大大
 * @description:TODO
 * @date :2022-01-23 14:11
 */
public class SecondLeaveCatcheTest {
        private InputStream in;
        private SqlSessionFactory factory;


        @Before//用于在测试方法执行之前执行
        public void init()throws  Exception{
            in = Resources.getResourceAsStream("SqlMapConfig.xml");
            SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
            factory = builder.build(in);

        }
        @After//用于在测试方法之后执行
        public void destory() throws Exception{
            in.close();
        }
        //一级缓存
        @Test
        public  void tesSecondChatch() throws  Exception {
            SqlSession sqlSession1 = factory.openSession();
            IUserDao dao1 =sqlSession1.getMapper(IUserDao.class);
            User user1 = dao1.findById(2);
            System.out.println(user1);
            sqlSession1.close(); //一级缓存消失

            SqlSession sqlSession2 = factory.openSession();
            IUserDao dao2 =sqlSession2.getMapper(IUserDao.class);
            User user2 = dao2.findById(2);
            System.out.println(user2);
            sqlSession2.close();
            System.out.println( user1 == user2);
        }

    }

结果

image.png

image.png

image.png

其中的

 System.out.println( user1 == user2);

输出的是false

image.png