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

鼠扑  金牌会员 | 2024-12-16 17:37:37 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 919|帖子 919|积分 2757

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

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


目前已经更新到了:



  • MyBatis(正在更新)
二级缓存整合 Redis

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

  1. <dependency>
  2.     <groupId>org.mybatis.caches</groupId>
  3.     <artifactId>mybatis-redis</artifactId>
  4.     <version>1.0.0-beta2</version>
  5. </dependency>
复制代码
编写代码

UserCacheMapper.xml

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper
  3.         PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4.         "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="icu.wzk.mapper.UserCacheMapper">
  6.     <!--开启二级缓存-->
  7.     <cache type="org.mybatis.caches.redis.RedisCache"></cache>
  8.     <resultMap id="userMap" type="icu.wzk.model.WzkUser">
  9.         <result column="id" property="id"></result>
  10.         <result column="username" property="username"></result>
  11.         <result column="password" property="password"></result>
  12.         <result column="birthday" property="birthday"></result>
  13.         <collection property="orderList" ofType="icu.wzk.model.WzkOrder">
  14.             <result column="oid" property="id"></result>
  15.             <result column="ordertime" property="ordertime"></result>
  16.             <result column="total" property="total"></result>
  17.         </collection>
  18.     </resultMap>
  19.     <select id="findAll" resultMap="userMap" useCache="true">
  20.         select *,o.id oid from wzk_user u left join wzk_orders o on u.id=o.uid;
  21.     </select>
  22. </mapper>
复制代码
UserCacheMapper.java

  1. public interface UserCacheMapper {
  2.     List<WzkUser> findAll();
  3. }
复制代码
redis.properties

  1. redis.host=10.10.52.11
  2. redis.port=31679
  3. redis.connectionTimeout=5000
  4. redis.password=
  5. redis.database=0
复制代码
测试代码

  1. public class WzkicuCache05 {
  2.     public static void main(String[] args) throws IOException {
  3.         InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml");
  4.         SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()
  5.                 .build(inputStream);
  6.         SqlSession sqlSession1 = sqlSessionFactory.openSession();
  7.         SqlSession sqlSession2 = sqlSessionFactory.openSession();
  8.         UserCacheMapper userCacheMapper1 = sqlSession1.getMapper(UserCacheMapper.class);
  9.         UserCacheMapper userCacheMapper2 = sqlSession2.getMapper(UserCacheMapper.class);
  10.         List<WzkUser> wzkUserList = userCacheMapper1.findAll();
  11.         for (WzkUser wu : wzkUserList) {
  12.             System.out.println(wu);
  13.         }
  14.         sqlSession1.close();
  15.         List<WzkUser> wzkUserList2 = userCacheMapper2.findAll();
  16.         for (WzkUser wu : wzkUserList2) {
  17.             System.out.println(wu);
  18.         }
  19.         sqlSession2.close();
  20.     }
  21. }
复制代码
运行效果

  1. WzkUser(id=1, username=wzk-update, password=123-update, birthday=Mon Nov 11 00:00:00 CST 2024, orderList=[WzkOrder(id=1, ord
复制代码
对应的效果如下图所示:

这里代码我运行了多次,可以看到请求都不会发出了,因为在 Redis 上缓存了。
源码分析

RedisCache 和其他的缓存方案基本是相似的,无非是实现了 Cache 接口,并使用 Jedis 操作缓存。
  1. public final class RedisCache implements Cache {
  2.     private final String id;
  3.     private final JedisPool pool;
  4.     public RedisCache(final String id) {
  5.         if (id == null) {
  6.             throw new IllegalArgumentException("Cache instances require an ID");
  7.         }
  8.         this.id = id;
  9.         RedisConfig redisConfig = RedisConfigurationBuilder.getInstance().parseConfiguration();
  10.         pool = new JedisPool(
  11.                 redisConfig,
  12.                 redisConfig.getHost(),
  13.                 redisConfig.getPort(),
  14.                 redisConfig.getConnectionTimeout(),
  15.                 redisConfig.getSoTimeout(),
  16.                 redisConfig.getPassword(),
  17.                 redisConfig.getDatabase(),
  18.                 redisConfig.getClientName()
  19.         );
  20.     }
  21. }
复制代码
RedisCache 在启动的时候,由 MyBatis 的 CacheBuilder 创建,创建的方式很简单,就是调用 RedisCache 的带有 String 参数的构造方法,即 RedisCache(String id),而 RedisCache 的构造方法中,调用了 RedisConfigurationBuilder 来创建对象 RedisConfig 对象,并使用 RedisConfig 来创建 JedisPool。
RedisConfig 继续了 JedisPoolConfig,提供了多个参数,这里的属性如下:
  1. private String host = Protocol.DEFAULT_HOST;
  2. private int port = Protocol.DEFAULT_PORT;
  3. private int connectionTimeout = Protocol.DEFAULT_TIMEOUT;
  4. private int soTimeout = Protocol.DEFAULT_TIMEOUT;
  5. private String password;
  6. private int database = Protocol.DEFAULT_DATABASE;
  7. private String clientName;
复制代码
对应的截图如下所示:

RedisConfig 对象是由 RedisConfigurationBuilder 创建的,简单看下这个类,最告急的方法就是 parse 的部门:
  1. public RedisConfig parseConfiguration(ClassLoader classLoader) {
  2.         Properties config = new Properties();
  3.         InputStream input = classLoader.getResourceAsStream(this.redisPropertiesFilename);
  4.         if (input != null) {
  5.             try {
  6.                 config.load(input);
  7.             } catch (IOException var12) {
  8.                 throw new RuntimeException("An error occurred while reading classpath property '" + this.redisPropertiesFilename + "', see nested exceptions", var12);
  9.             } finally {
  10.                 try {
  11.                     input.close();
  12.                 } catch (IOException var11) {
  13.                 }
  14.             }
  15.         }
  16.         RedisConfig jedisConfig = new RedisConfig();
  17.         this.setConfigProperties(config, jedisConfig);
  18.         return jedisConfig;
  19.     }
复制代码
对应的截图如下所示:

我们从这里看出,从 classpath 下读取了一个 redis.properties:
  1. private final String redisPropertiesFilename = System.getProperty("redis.properties.filename", "redis.properties");
复制代码
并将该设置文件中内容设置到了 RedisConfig 对象中,并返回,接下来,就是 RedisCache 使用 RedisConfig 类创建完成 JedisPool。
在 RedisCache 中,有一个模板方法:
  1.   private Object execute(RedisCallback callback) {
  2.     Jedis jedis = pool.getResource();
  3.     try {
  4.       return callback.doWithRedis(jedis);
  5.     } finally {
  6.       jedis.close();
  7.     }
  8.   }
复制代码
对应的截图如下所示:

模板接口为 RedisCallback,接口中只实现了一个 doWithRedis 方法而已:
  1. package org.mybatis.caches.redis;
  2. import redis.clients.jedis.Jedis;
  3. public interface RedisCallback {
  4.         Object doWithRedis(Jedis jedis);
  5. }
复制代码
对应的截图如下所示:


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

鼠扑

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表