MyBatis 教程

MyBatis 指定二级缓存大小

本文将介绍怎样使用 <cache> 标签指定二级缓存策略、以及缓存大小。如下:

<!-- evication LRU 最近最少使用-->
<cache eviction="LRU" size="2" />

上面指定缓存策略为 LRU(最近最少使用),缓存大小为2个对象。

什么是LRU?

LRU是Least Recently Used的缩写,即最近最少使用,是一种常用的页面置换算法,选择最近最久未使用的页面予以淘汰。该算法赋予每个页面一个访问字段,用来记录一个页面自上次被访问以来所经历的时间 t,当须淘汰一个页面时,选择现有页面中其 t 值最大的,即最近最少使用的页面予以淘汰。

示例代码

(1)MyBatis 配置文件 mybatis-cfg.xml 内容如下:

<?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="database.properties"/>
    <settings>
        <!-- 全局映射器启用缓存 -->
        <setting name="cacheEnabled" value="true" />
    </settings>
    <environments default="MySqlDatabase" >
        <environment id="MySqlDatabase" >
            <transactionManager type="JDBC" />
            <dataSource type="POOLED">
                <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/hxstrive/mybatis/cache/demo3/UserMapper.xml" />
    </mappers>
</configuration>

(2)定义 JavaBean UserBean.java,代码如下:

package com.hxstrive.mybatis.cache.demo3;

import java.io.Serializable;

public class UserBean implements Serializable {
   private Integer userId;
   private String name;
   private String sex;
   private Integer age;
   // 忽略 getter 和 setter 方法
}

(3)定义 Mapper

a、UserMapper.java

package com.hxstrive.mybatis.cache.demo3;

import org.apache.ibatis.annotations.Param;

public interface UserMapper {
   // 根据用户ID获取用户信息
   UserBean getUserById(@Param("userId") int userId);
}

b、UserMapper.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.hxstrive.mybatis.cache.demo3.UserMapper">

   <!-- 开启二级缓存 -->
   <!-- evication LRU 最近最少使用-->
   <cache eviction="LRU"
      size="2" />

   <!-- 映射结果 -->
   <resultMap id="RESULT_MAP" type="com.hxstrive.mybatis.cache.demo3.UserBean">
      <id column="user_id" jdbcType="INTEGER" property="userId" />
      <result column="name" jdbcType="VARCHAR" property="name" />
      <result column="sex" jdbcType="VARCHAR" property="sex" />
      <result column="age" jdbcType="INTEGER" property="age" />
   </resultMap>

   <!-- 查询所有用户信息 -->
   <select id="getUserById" resultMap="RESULT_MAP" useCache="true">
      select `user_id`, `name`, `sex`, `age`
      from `user` where `user_id`=#{userId}
   </select>

</mapper>

(4)客户端代码:

package com.hxstrive.mybatis.cache.demo3;

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 java.io.InputStream;

public class CacheDemo {

	public static void main(String[] args) throws Exception {
		String cfgName = "com/hxstrive/mybatis/cache/demo3/mybatis-cfg.xml";
		InputStream input = Resources.getResourceAsStream(cfgName);
		SqlSessionFactoryBuilder factoryBuilder = new SqlSessionFactoryBuilder();
		SqlSessionFactory sqlFactory = factoryBuilder.build(input);
		getUserById(sqlFactory, 1);
		getUserById(sqlFactory, 2);
		getUserById(sqlFactory, 3);
		getUserById(sqlFactory, 3);
		getUserById(sqlFactory, 2);
		getUserById(sqlFactory, 1);
	}

	private static void getUserById(SqlSessionFactory sqlFactory, int userId) {
		System.out.println("查询用户信息:");
		SqlSession sqlSession = sqlFactory.openSession();
		UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
		UserBean userBean = userMapper.getUserById(userId);
		System.out.println(userBean + " -- " + userBean.getName());
		sqlSession.close();
	}

}

运行上面客户端代码,输出结果如下:

2020-09-07 22:28:21,772 DEBUG [org.apache.ibatis.logging.LogFactory] - Logging initialized using 'class org.apache.ibatis.logging.slf4j.Slf4jImpl' adapter.
2020-09-07 22:28:21,790 DEBUG [org.apache.ibatis.datasource.pooled.PooledDataSource] - PooledDataSource forcefully closed/removed all connections.
2020-09-07 22:28:21,790 DEBUG [org.apache.ibatis.datasource.pooled.PooledDataSource] - PooledDataSource forcefully closed/removed all connections.
2020-09-07 22:28:21,790 DEBUG [org.apache.ibatis.datasource.pooled.PooledDataSource] - PooledDataSource forcefully closed/removed all connections.
2020-09-07 22:28:21,790 DEBUG [org.apache.ibatis.datasource.pooled.PooledDataSource] - PooledDataSource forcefully closed/removed all connections.
查询用户信息:
2020-09-07 22:28:22,345 DEBUG [org.apache.ibatis.cache.decorators.LoggingCache] - Cache Hit Ratio [com.hxstrive.mybatis.cache.demo3.UserMapper]: 0.0
2020-09-07 22:28:22,367 DEBUG [org.apache.ibatis.transaction.jdbc.JdbcTransaction] - Opening JDBC Connection
2020-09-07 22:28:23,000 DEBUG [org.apache.ibatis.datasource.pooled.PooledDataSource] - Created connection 922872566.
2020-09-07 22:28:23,000 DEBUG [org.apache.ibatis.transaction.jdbc.JdbcTransaction] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@3701eaf6]
2020-09-07 22:28:23,002 DEBUG [com.hxstrive.mybatis.cache.demo3.UserMapper.getUserById] - ooo Using Connection [com.mysql.jdbc.JDBC4Connection@3701eaf6]
2020-09-07 22:28:23,003 DEBUG [com.hxstrive.mybatis.cache.demo3.UserMapper.getUserById] - ==>  Preparing: select `user_id`, `name`, `sex`, `age` from `user` where `user_id`=? 
2020-09-07 22:28:23,036 DEBUG [com.hxstrive.mybatis.cache.demo3.UserMapper.getUserById] - ==> Parameters: 1(Integer)
2020-09-07 22:28:23,073 DEBUG [com.hxstrive.mybatis.cache.demo3.UserMapper.getUserById] - <==      Total: 1
com.hxstrive.mybatis.cache.demo3.UserBean@76707e36 -- Helen
2020-09-07 22:28:23,096 DEBUG [org.apache.ibatis.transaction.jdbc.JdbcTransaction] - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@3701eaf6]
2020-09-07 22:28:23,097 DEBUG [org.apache.ibatis.transaction.jdbc.JdbcTransaction] - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@3701eaf6]
2020-09-07 22:28:23,098 DEBUG [org.apache.ibatis.datasource.pooled.PooledDataSource] - Returned connection 922872566 to pool.
查询用户信息:
2020-09-07 22:28:23,098 DEBUG [org.apache.ibatis.cache.decorators.LoggingCache] - Cache Hit Ratio [com.hxstrive.mybatis.cache.demo3.UserMapper]: 0.0
2020-09-07 22:28:23,098 DEBUG [org.apache.ibatis.transaction.jdbc.JdbcTransaction] - Opening JDBC Connection
2020-09-07 22:28:23,098 DEBUG [org.apache.ibatis.datasource.pooled.PooledDataSource] - Checked out connection 922872566 from pool.
2020-09-07 22:28:23,098 DEBUG [org.apache.ibatis.transaction.jdbc.JdbcTransaction] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@3701eaf6]
2020-09-07 22:28:23,099 DEBUG [com.hxstrive.mybatis.cache.demo3.UserMapper.getUserById] - ooo Using Connection [com.mysql.jdbc.JDBC4Connection@3701eaf6]
2020-09-07 22:28:23,099 DEBUG [com.hxstrive.mybatis.cache.demo3.UserMapper.getUserById] - ==>  Preparing: select `user_id`, `name`, `sex`, `age` from `user` where `user_id`=? 
2020-09-07 22:28:23,099 DEBUG [com.hxstrive.mybatis.cache.demo3.UserMapper.getUserById] - ==> Parameters: 2(Integer)
2020-09-07 22:28:23,101 DEBUG [com.hxstrive.mybatis.cache.demo3.UserMapper.getUserById] - <==      Total: 1
com.hxstrive.mybatis.cache.demo3.UserBean@27a5f880 -- 张小凡
2020-09-07 22:28:23,101 DEBUG [org.apache.ibatis.transaction.jdbc.JdbcTransaction] - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@3701eaf6]
2020-09-07 22:28:23,102 DEBUG [org.apache.ibatis.transaction.jdbc.JdbcTransaction] - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@3701eaf6]
2020-09-07 22:28:23,102 DEBUG [org.apache.ibatis.datasource.pooled.PooledDataSource] - Returned connection 922872566 to pool.
查询用户信息:
2020-09-07 22:28:23,102 DEBUG [org.apache.ibatis.cache.decorators.LoggingCache] - Cache Hit Ratio [com.hxstrive.mybatis.cache.demo3.UserMapper]: 0.0
2020-09-07 22:28:23,102 DEBUG [org.apache.ibatis.transaction.jdbc.JdbcTransaction] - Opening JDBC Connection
2020-09-07 22:28:23,102 DEBUG [org.apache.ibatis.datasource.pooled.PooledDataSource] - Checked out connection 922872566 from pool.
2020-09-07 22:28:23,103 DEBUG [org.apache.ibatis.transaction.jdbc.JdbcTransaction] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@3701eaf6]
2020-09-07 22:28:23,103 DEBUG [com.hxstrive.mybatis.cache.demo3.UserMapper.getUserById] - ooo Using Connection [com.mysql.jdbc.JDBC4Connection@3701eaf6]
2020-09-07 22:28:23,103 DEBUG [com.hxstrive.mybatis.cache.demo3.UserMapper.getUserById] - ==>  Preparing: select `user_id`, `name`, `sex`, `age` from `user` where `user_id`=? 
2020-09-07 22:28:23,103 DEBUG [com.hxstrive.mybatis.cache.demo3.UserMapper.getUserById] - ==> Parameters: 3(Integer)
2020-09-07 22:28:23,106 DEBUG [com.hxstrive.mybatis.cache.demo3.UserMapper.getUserById] - <==      Total: 1
com.hxstrive.mybatis.cache.demo3.UserBean@15d0c81b -- 叶星云
2020-09-07 22:28:23,106 DEBUG [org.apache.ibatis.transaction.jdbc.JdbcTransaction] - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@3701eaf6]
2020-09-07 22:28:23,107 DEBUG [org.apache.ibatis.transaction.jdbc.JdbcTransaction] - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@3701eaf6]
2020-09-07 22:28:23,107 DEBUG [org.apache.ibatis.datasource.pooled.PooledDataSource] - Returned connection 922872566 to pool.
查询用户信息:
2020-09-07 22:28:23,110 DEBUG [org.apache.ibatis.cache.decorators.LoggingCache] - Cache Hit Ratio [com.hxstrive.mybatis.cache.demo3.UserMapper]: 0.25
com.hxstrive.mybatis.cache.demo3.UserBean@2833cc44 -- 叶星云
查询用户信息:
2020-09-07 22:28:23,111 DEBUG [org.apache.ibatis.cache.decorators.LoggingCache] - Cache Hit Ratio [com.hxstrive.mybatis.cache.demo3.UserMapper]: 0.4
com.hxstrive.mybatis.cache.demo3.UserBean@33f88ab -- 张小凡
查询用户信息:
2020-09-07 22:28:23,111 DEBUG [org.apache.ibatis.cache.decorators.LoggingCache] - Cache Hit Ratio [com.hxstrive.mybatis.cache.demo3.UserMapper]: 0.3333333333333333
2020-09-07 22:28:23,112 DEBUG [org.apache.ibatis.transaction.jdbc.JdbcTransaction] - Opening JDBC Connection
2020-09-07 22:28:23,112 DEBUG [org.apache.ibatis.datasource.pooled.PooledDataSource] - Checked out connection 922872566 from pool.
2020-09-07 22:28:23,112 DEBUG [org.apache.ibatis.transaction.jdbc.JdbcTransaction] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@3701eaf6]
2020-09-07 22:28:23,112 DEBUG [com.hxstrive.mybatis.cache.demo3.UserMapper.getUserById] - ooo Using Connection [com.mysql.jdbc.JDBC4Connection@3701eaf6]
2020-09-07 22:28:23,113 DEBUG [com.hxstrive.mybatis.cache.demo3.UserMapper.getUserById] - ==>  Preparing: select `user_id`, `name`, `sex`, `age` from `user` where `user_id`=? 
2020-09-07 22:28:23,113 DEBUG [com.hxstrive.mybatis.cache.demo3.UserMapper.getUserById] - ==> Parameters: 1(Integer)
2020-09-07 22:28:23,115 DEBUG [com.hxstrive.mybatis.cache.demo3.UserMapper.getUserById] - <==      Total: 1
com.hxstrive.mybatis.cache.demo3.UserBean@536aaa8d -- Helen
2020-09-07 22:28:23,115 DEBUG [org.apache.ibatis.transaction.jdbc.JdbcTransaction] - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@3701eaf6]
2020-09-07 22:28:23,116 DEBUG [org.apache.ibatis.transaction.jdbc.JdbcTransaction] - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@3701eaf6]
2020-09-07 22:28:23,116 DEBUG [org.apache.ibatis.datasource.pooled.PooledDataSource] - Returned connection 922872566 to pool.

根据上面的结果可以得知,如下规律:

来自数据库 —— com.hxstrive.mybatis.cache.demo3.UserBean@76707e36 -- Helen(被缓存了,然后被淘汰了)
来自数据库 —— com.hxstrive.mybatis.cache.demo3.UserBean@27a5f880 -- 张小凡(被缓存了)
来自数据库 —— com.hxstrive.mybatis.cache.demo3.UserBean@15d0c81b -- 叶星云(被缓存了)
从缓存获取 —— com.hxstrive.mybatis.cache.demo3.UserBean@2833cc44 -- 叶星云
从缓存获取 —— com.hxstrive.mybatis.cache.demo3.UserBean@33f88ab -- 张小凡
来自数据库 —— com.hxstrive.mybatis.cache.demo3.UserBean@536aaa8d -- Helen(没有命中,从数据库读取)

说明 MyBatis 只缓存了两个对象。如果你将上面客户端调用 getUserById 的顺序进行调整,如下:

getUserById(sqlFactory, 1); —— 从数据库查询,然后缓存,缓存 [1]
getUserById(sqlFactory, 2); —— 缓存未命中,从数据库查询,然后缓存,缓存 [1, 2]
getUserById(sqlFactory, 3); —— 缓存未命中,从数据库查询,然后将 ID=1 淘汰,添加当前对象到缓存,缓存 [2, 3]
getUserById(sqlFactory, 1); —— 缓存未命中,从数据库查询,然后将 ID=2 淘汰,添加当前对象到缓存,缓存 [3, 1]
getUserById(sqlFactory, 2); —— 缓存未命中,从数据库查询,然后将 ID=3 淘汰,添加当前对象到缓存,缓存 [1, 2]
getUserById(sqlFactory, 3); —— 缓存未命中,从数据库查询,然后将 ID=1 淘汰,添加当前对象到缓存,缓存 [2, 3]

你会发现上面6次调用 getUserById 缓存命中率为0,所以调用顺序对缓存很重要。更多缓存知识需要读者去探索……

说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
公众号