鼠扑 发表于 2024-12-16 17:37:37

Java-13 深入浅出 MyBatis - 二级缓存整合Redis 代码测试 与 原理探究 源码

点一下关注吧!!!非常感谢!!连续更新!!!

大数据篇正在更新!https://blog.csdn.net/w776341482/category_12713819.html

https://i-blog.csdnimg.cn/direct/95d0444220434b97a2a45998cc5ce8b9.png
目前已经更新到了:



[*]MyBatis(正在更新)
二级缓存整合 Redis

目前我们实现的二级缓存是每个服务的,此时缓存是在单个服务器上,如果我们想要实现分布式缓存的话,此时我们就必要考虑 Redis 来做我们的缓存服务。
以是接下来,我们将对 MyBatis 和 Redis 进行一个整合。
在 MyBatis 中,提供了一个针对 Cache 的接口,MyBatis 还提供了一个针对 Cache 接口的 Redis 实现类,该类存在在 myBatis-redis 包中。
pom.xml

<dependency>
    <groupId>org.mybatis.caches</groupId>
    <artifactId>mybatis-redis</artifactId>
    <version>1.0.0-beta2</version>
</dependency>
编写代码

UserCacheMapper.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="icu.wzk.mapper.UserCacheMapper">

    <!--开启二级缓存-->
    <cache type="org.mybatis.caches.redis.RedisCache"></cache>

    <resultMap id="userMap" type="icu.wzk.model.WzkUser">
      <result column="id" property="id"></result>
      <result column="username" property="username"></result>
      <result column="password" property="password"></result>
      <result column="birthday" property="birthday"></result>
      <collection property="orderList" ofType="icu.wzk.model.WzkOrder">
            <result column="oid" property="id"></result>
            <result column="ordertime" property="ordertime"></result>
            <result column="total" property="total"></result>
      </collection>
    </resultMap>

    <select id="findAll" resultMap="userMap" useCache="true">
      select *,o.id oid from wzk_user u left join wzk_orders o on u.id=o.uid;
    </select>
</mapper>

UserCacheMapper.java

public interface UserCacheMapper {
    List<WzkUser> findAll();
}
redis.properties

redis.host=10.10.52.11
redis.port=31679
redis.connectionTimeout=5000
redis.password=
redis.database=0
测试代码

public class WzkicuCache05 {

    public static void main(String[] args) throws IOException {
      InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml");
      SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()
                .build(inputStream);
      SqlSession sqlSession1 = sqlSessionFactory.openSession();
      SqlSession sqlSession2 = sqlSessionFactory.openSession();

      UserCacheMapper userCacheMapper1 = sqlSession1.getMapper(UserCacheMapper.class);
      UserCacheMapper userCacheMapper2 = sqlSession2.getMapper(UserCacheMapper.class);
      List<WzkUser> wzkUserList = userCacheMapper1.findAll();
      for (WzkUser wu : wzkUserList) {
            System.out.println(wu);
      }
      sqlSession1.close();

      List<WzkUser> wzkUserList2 = userCacheMapper2.findAll();
      for (WzkUser wu : wzkUserList2) {
            System.out.println(wu);
      }
      sqlSession2.close();
    }

}

运行效果

WzkUser(id=1, username=wzk-update, password=123-update, birthday=Mon Nov 11 00:00:00 CST 2024, orderList=[WzkOrder(id=1, ord
对应的效果如下图所示:
https://i-blog.csdnimg.cn/direct/42f85cf6ac58491a94d46ac971717369.png
这里代码我运行了多次,可以看到请求都不会发出了,因为在 Redis 上缓存了。
源码分析

RedisCache 和其他的缓存方案基本是相似的,无非是实现了 Cache 接口,并使用 Jedis 操作缓存。
public final class RedisCache implements Cache {

    private final String id;
    private final JedisPool pool;

    public RedisCache(final String id) {
      if (id == null) {
            throw new IllegalArgumentException("Cache instances require an ID");
      }
      this.id = id;

      RedisConfig redisConfig = RedisConfigurationBuilder.getInstance().parseConfiguration();

      pool = new JedisPool(
                redisConfig,
                redisConfig.getHost(),
                redisConfig.getPort(),
                redisConfig.getConnectionTimeout(),
                redisConfig.getSoTimeout(),
                redisConfig.getPassword(),
                redisConfig.getDatabase(),
                redisConfig.getClientName()
      );
    }
}

RedisCache 在启动的时候,由 MyBatis 的 CacheBuilder 创建,创建的方式很简单,就是调用 RedisCache 的带有 String 参数的构造方法,即 RedisCache(String id),而 RedisCache 的构造方法中,调用了 RedisConfigurationBuilder 来创建对象 RedisConfig 对象,并使用 RedisConfig 来创建 JedisPool。
RedisConfig 继续了 JedisPoolConfig,提供了多个参数,这里的属性如下:
private String host = Protocol.DEFAULT_HOST;
private int port = Protocol.DEFAULT_PORT;
private int connectionTimeout = Protocol.DEFAULT_TIMEOUT;
private int soTimeout = Protocol.DEFAULT_TIMEOUT;
private String password;
private int database = Protocol.DEFAULT_DATABASE;
private String clientName;
对应的截图如下所示:
https://i-blog.csdnimg.cn/direct/5ee41d1ef2ea47929124703558820fdb.png
RedisConfig 对象是由 RedisConfigurationBuilder 创建的,简单看下这个类,最告急的方法就是 parse 的部门:
public RedisConfig parseConfiguration(ClassLoader classLoader) {
      Properties config = new Properties();
      InputStream input = classLoader.getResourceAsStream(this.redisPropertiesFilename);
      if (input != null) {
            try {
                config.load(input);
            } catch (IOException var12) {
                throw new RuntimeException("An error occurred while reading classpath property '" + this.redisPropertiesFilename + "', see nested exceptions", var12);
            } finally {
                try {
                  input.close();
                } catch (IOException var11) {
                }

            }
      }

      RedisConfig jedisConfig = new RedisConfig();
      this.setConfigProperties(config, jedisConfig);
      return jedisConfig;
    }
对应的截图如下所示:
https://i-blog.csdnimg.cn/direct/2cecf78a8331464492951b6d38c8389f.png
我们从这里看出,从 classpath 下读取了一个 redis.properties:
private final String redisPropertiesFilename = System.getProperty("redis.properties.filename", "redis.properties");
并将该设置文件中内容设置到了 RedisConfig 对象中,并返回,接下来,就是 RedisCache 使用 RedisConfig 类创建完成 JedisPool。
在 RedisCache 中,有一个模板方法:
private Object execute(RedisCallback callback) {
    Jedis jedis = pool.getResource();
    try {
      return callback.doWithRedis(jedis);
    } finally {
      jedis.close();
    }
}
对应的截图如下所示:
https://i-blog.csdnimg.cn/direct/bb5651fa2a3f44ad9961eaa9a8ac77d3.png
模板接口为 RedisCallback,接口中只实现了一个 doWithRedis 方法而已:
package org.mybatis.caches.redis;

import redis.clients.jedis.Jedis;

public interface RedisCallback {

        Object doWithRedis(Jedis jedis);
}

对应的截图如下所示:
https://i-blog.csdnimg.cn/direct/a7e831a99b534f7b9e146b7c3ae9bb3c.png

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: Java-13 深入浅出 MyBatis - 二级缓存整合Redis 代码测试 与 原理探究 源码