【Mybatis 一、二级缓存实用详解】

Mybatis缓存

一级缓存:
一级缓存的作用域是sqlSession级别,同一个sqlSession中执行相同的sql查询(相同的SQL和参数),第一次会去查询数据库并写到一级缓存中,第二次则会从一级缓存中直接获取。
二级缓存:
二级缓存的作用域是sqlSessionFactory的Mapper映射级别,是Mybatis中SqlSessionFactory对象的缓存。由同一个SqlSessionFactory对象创建的多个 SqlSession 去操作同一个 Mapper 映射的 sql 语句,多个SqlSession 可以共用二级缓存,二级缓存是跨 SqlSession 的。

配置实例

Demo架构

在这里插入图片描述

public class Chapter3Main {
    Logger log = Logger.getLogger(Chapter3Main.class);

    public static void main(String[] args) {
        testRoleMapper1();
        //testRoleMapper2();
        //testRoleMapper3();
        //testRoleMapper4();
        //testRoleMapper5();

    }

    //一级缓存 同一sqlSession执行相同的sql
    private static void testRoleMapper1() {

        SqlSession sqlSession = null;
        try {
            sqlSession = SqlSessionFactoryUtils.openSqlSession();
            RoleMapper roleMapper = sqlSession.getMapper(RoleMapper.class);
            Role role = roleMapper.getRole(9);
            System.out.println("role:" + role);
            role = roleMapper.getRole(9);
            System.out.println("role:" + role);
        } finally {
            if (sqlSession != null) {
                sqlSession.close();
            }
        }
    }

    //一级缓存 不同的sqlSession执行相同的sql
    private static void testRoleMapper2() {

        SqlSession sqlSession1 = null;
        SqlSession sqlSession2 = null;
        try {
            sqlSession1 = SqlSessionFactoryUtils.openSqlSession();
            sqlSession2 = SqlSessionFactoryUtils.openSqlSession();
            RoleMapper roleMapper1 = sqlSession1.getMapper(RoleMapper.class);
            Role role1 = roleMapper1.getRole(9);
            System.out.println("role:" + role1);

            RoleMapper roleMapper2 = sqlSession2.getMapper(RoleMapper.class);

            Role role2 = roleMapper2.getRole(9);
            System.out.println("role:" + role2);
        } finally {
            if (sqlSession1 != null) {
                sqlSession1.close();
            }
            if (sqlSession2 != null) {
                sqlSession2.close();
            }
        }
    }

    //二级缓存 RoleMapper.xml 有/无<cache/>测试
    private static void testRoleMapper3() {

        SqlSession sqlSession1 = null;
        SqlSession sqlSession2 = null;
        try {
            sqlSession1 = SqlSessionFactoryUtils.openSqlSession();
            sqlSession2 = SqlSessionFactoryUtils.openSqlSession();
            RoleMapper roleMapper1 = sqlSession1.getMapper(RoleMapper.class);
            Role role1 = roleMapper1.getRole(9);
            System.out.println("role:" + role1);
            sqlSession1.commit();
            RoleMapper roleMapper2 = sqlSession2.getMapper(RoleMapper.class);

            Role role2 = roleMapper2.getRole(9);
            System.out.println("role:" + role2);
            sqlSession1.commit();
        } finally {
            if (sqlSession1 != null) {
                sqlSession1.close();
            }
            if (sqlSession2 != null) {
                sqlSession2.close();
            }
        }
    }
    //二级缓存 <setting name="cacheEnabled" value="false"/>情况下 <cache/>有无测试
    private static void testRoleMapper4() {

        SqlSession sqlSession1 = null;
        SqlSession sqlSession2 = null;
        try {
            sqlSession1 = SqlSessionFactoryUtils.openSqlSession();
            sqlSession2 = SqlSessionFactoryUtils.openSqlSession();
            RoleMapper roleMapper1 = sqlSession1.getMapper(RoleMapper.class);
            Role role1 = roleMapper1.getRole(9);
            System.out.println("role:" + role1);
            sqlSession1.commit();
            RoleMapper roleMapper2 = sqlSession2.getMapper(RoleMapper.class);

            Role role2 = roleMapper2.getRole(9);
            System.out.println("role:" + role2);
            sqlSession1.commit();
        } finally {
            if (sqlSession1 != null) {
                sqlSession1.close();
            }
            if (sqlSession2 != null) {
                sqlSession2.close();
            }
        }
    }

//全局开启二级缓存 单独某个select关闭二级缓存
    private static void testRoleMapper5() {

        SqlSession sqlSession1 = null;
        SqlSession sqlSession2 = null;
        try {
            sqlSession1 = SqlSessionFactoryUtils.openSqlSession();
            sqlSession2 = SqlSessionFactoryUtils.openSqlSession();
            RoleMapper roleMapper1 = sqlSession1.getMapper(RoleMapper.class);
            List<Role> role1 = roleMapper1.getRoleByName("geng");
            System.out.println("role:" + role1);
            sqlSession1.commit();
            RoleMapper roleMapper2 = sqlSession2.getMapper(RoleMapper.class);
            List<Role> role2 = roleMapper2.getRoleByName("geng");
            System.out.println("role:" + role2);
            sqlSession1.commit();
        } finally {
            if (sqlSession1 != null) {
                sqlSession1.close();
            }
            if (sqlSession2 != null) {
                sqlSession2.close();
            }
        }
    }

}
public interface RoleMapper {
    public Role getRole(int id);
    public ArrayList<Role> getRoleByName(@Param("roleName") String roleName);
}
@Data
public class Role implements Serializable {
    private int roleId;
    private String roleName;
    private int roleAge;
}
public class SqlSessionFactoryUtils {

    private final static Class<SqlSessionFactoryUtils> LOCK = SqlSessionFactoryUtils.class;

    private static SqlSessionFactory sqlSessionFactory = null;

    private SqlSessionFactoryUtils() {
    }

    public static SqlSessionFactory getSqlSessionFactory() {
        synchronized (LOCK) {
            if (sqlSessionFactory != null) {
                return sqlSessionFactory;
            }
            String resource = "mapper/mybatis-config.xml";
            InputStream inputStream;
            try {
                inputStream = Resources.getResourceAsStream(resource);
                sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            } catch (IOException e) {
                e.printStackTrace();
                return null;
            }
            return sqlSessionFactory;
        }
    }


    public static SqlSession openSqlSession() {
        if (sqlSessionFactory == null) {
            getSqlSessionFactory();
        }
        return sqlSessionFactory.openSession();
    }
<?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>
    <settings>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>
    <typeAliases><!-- 别名 -->
        <package name="com.example.mybatismapper.pojo"/>
    </typeAliases>
    <!-- 数据库环境 -->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url"
                          value="jdbc:mysql://127.0.0.1/springmvc_db?useUnicode=true&amp;characterEncoding=utf-8&amp;serverTimezone=UTC&amp;useSSL=true"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
    <!-- 映射文件 -->
    <mappers>
        <mapper resource="mapper/RoleMapper.xml"/>
    </mappers>
</configuration>
<?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.example.mybatismapper.mapper.RoleMapper">

    <select id="getRole" parameterType="int" resultType="Role" >
        select *
        from role
        where role_id = #{id}
    </select>

    <select id="getRoleByName" parameterType="string" resultType="Role">
        select *
        from role
        where role_name like concat('%', #{roleName}, '%')
    </select>

</mapper>
CREATE TABLE `role` (
  `role_id` int NOT NULL AUTO_INCREMENT,
  `role_name` varchar(255) DEFAULT NULL,
  `role_age` int DEFAULT NULL,
  PRIMARY KEY (`role_id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8

Mybatis配置setting配置项:
——该配置影响所有映射器中配置缓存的全局开关 默认true;
cache元素的属性配置自行百度;
select元素的属性配置:
flushCache——它的作用是在调用sql后,是否要求Mybatis清空之前查询本地缓存和二级缓存 默认false;
useCache——启动二级缓存的开关,是否要求Mybatis将此次结果缓存 默认值true;

一级缓存

在这里插入图片描述
同一个sqlSession执行了两次相同的sql,但只有第一次去数据库查询了,第二次直接从一级缓存中获取的查询结果;

在这里插入图片描述
两个不同的sqlSession执行相同的sql,两次sql都去数据库查询了。说明一级缓存是sqlSession级别的缓存

二级缓存

因为cacheEnabled默认是true,要想开启二级缓存则直接在映射文件中加上 cache 标签即可(各种属性可自行配置)。
在这里插入图片描述
在这里插入图片描述
两个不同的sqlSession执行相同的sql,但只有第一次去数据库查询了,第二次直接从二级缓存中获取的查询结果;

将cacheEnabled设置为false:
在这里插入图片描述
两个不同的sqlSession执行相同的sql,两次sql都去数据库查询了,说明没有走二级缓存。

select相关配置

useCache

cacheEnabled设置回为true:将getRoleByName sql查询语句useCache设置为"false"——全局开启二级缓存,但方法getRoleByName 关闭二级缓存(useCache细化二级缓存的应用语句)
在这里插入图片描述
在这里插入图片描述
可看出getRoleByNameSQL语句执行了两次数据库查询, 没有走二级缓存。

flushCache
一级缓存

在这里插入图片描述
在这里插入图片描述
同一个sqlSession执行了两次相同的sql,两次sql都去数据库查询了,说明没有走一级缓存。

二级缓存

在这里插入图片描述
在这里插入图片描述
两个不同的sqlSession执行相同的sql,两次sql都去数据库查询了,说明没有走二级缓存。

总结

1. 当 Mybatis 调用 Dao 层查询数据库时,会先查询二级缓存,二级缓存中无对应数据,再去查询一级缓存,一级缓存中也没有,最后去数据库查找。
2. sqlSession执行完commit操作(执行insert、update、delete)后,会清空SqlSession中的一级缓存;在关闭(close)sqlSession后,会把该sqlSession一级缓存中的数据添加到namespace映射的Mapper的二级缓存中。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值