使用 mybatis 的redis-cache 实现dao层缓存,配置方式非写代码

前言


本文的原文连接是: https://blog.csdn.net/freewebsys/article/details/91410171
未经博主允许不得转载。
博主地址是:http://blog.csdn.net/freewebsys

1,关于mybatis


其实还是有个古老的办法,有简单的办法做cache,但是大家还是习惯去硬编码。
其实不好,应该考虑用统一的方式,非硬编码的方式去做cache。
在加入cache的时候方便,在去掉的时候也方便。
https://www.w3cschool.cn/mybatis/7zy61ilv.html

github:
https://github.com/mybatis/redis-cache

2,使用


修改 mybatis 启用缓存:

然后设置cache:

配置在redis.properties:

redis.host=localhost
redis.port=6379
redis.connectionTimeout=5000
redis.soTimeout=5000
redis.password=
redis.database=0
redis.clientName=

#serializer type(kryo or jdk with jdk being default)
redis.serializer=jdk

其中需要实现 org.apache.ibatis.cache.cache 接口。有个构造函数:

public interface Cache {

  /**
   * @return The identifier of this cache
   */
  String getId();

  /**
   * @param key Can be any object but usually it is a {@link CacheKey}
   * @param value The result of a select.
   */
  void putObject(Object key, Object value);

  /**
   * @param key The key
   * @return The object stored in the cache.
   */
  Object getObject(Object key);

  /**
   * As of 3.3.0 this method is only called during a rollback 
   * for any previous value that was missing in the cache.
   * This lets any blocking cache to release the lock that 
   * may have previously put on the key.
   * A blocking cache puts a lock when a value is null 
   * and releases it when the value is back again.
   * This way other threads will wait for the value to be 
   * available instead of hitting the database.
   *
   * 
   * @param key The key
   * @return Not used
   */
  Object removeObject(Object key);

  /**
   * Clears this cache instance
   */  
  void clear();

  /**
   * Optional. This method is not called by the core.
   * 
   * @return The number of elements stored in the cache (not its capacity).
   */
  int getSize();
  
  /** 
   * Optional. As of 3.2.6 this method is no longer called by the core.
   *  
   * Any locking needed by the cache must be provided internally by the cache provider.
   * 
   * @return A ReadWriteLock 
   */
  ReadWriteLock getReadWriteLock();

}

而redis 的实现是:
https://github.com/mybatis/redis-cache/blob/master/src/main/java/org/mybatis/caches/redis/RedisCache.java

package org.mybatis.caches.redis;

import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock;

import org.apache.ibatis.cache.Cache;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

/**
 * Cache adapter for Redis.
 *
 * @author Eduardo Macarron
 */
public final class RedisCache implements Cache {

  private final ReadWriteLock readWriteLock = new DummyReadWriteLock();

  private String id;

  private static JedisPool pool;

  private final RedisConfig redisConfig;

  private Integer timeout;

  public RedisCache(final String id) {
    if (id == null) {
      throw new IllegalArgumentException("Cache instances require an ID");
    }
    this.id = id;
    redisConfig = RedisConfigurationBuilder.getInstance().parseConfiguration();
    pool = new JedisPool(redisConfig, redisConfig.getHost(), redisConfig.getPort(), redisConfig.getConnectionTimeout(),
        redisConfig.getSoTimeout(), redisConfig.getPassword(), redisConfig.getDatabase(), redisConfig.getClientName(),
        redisConfig.isSsl(), redisConfig.getSslSocketFactory(), redisConfig.getSslParameters(),
        redisConfig.getHostnameVerifier());
  }

  // TODO Review this is UNUSED
  private Object execute(RedisCallback callback) {
    Jedis jedis = pool.getResource();
    try {
      return callback.doWithRedis(jedis);
    } finally {
      jedis.close();
    }
  }

  @Override
  public String getId() {
    return this.id;
  }

  @Override
  public int getSize() {
    return (Integer) execute(new RedisCallback() {
      @Override
      public Object doWithRedis(Jedis jedis) {
        Map<byte[], byte[]> result = jedis.hgetAll(id.getBytes());
        return result.size();
      }
    });
  }

  @Override
  public void putObject(final Object key, final Object value) {
    execute(new RedisCallback() {
      @Override
      public Object doWithRedis(Jedis jedis) {
        final byte[] idBytes = id.getBytes();
        jedis.hset(idBytes, key.toString().getBytes(), redisConfig.getSerializer().serialize(value));
        if (timeout != null && jedis.ttl(idBytes) == -1) {
          jedis.expire(idBytes, timeout);
        }
        return null;
      }
    });
  }

  @Override
  public Object getObject(final Object key) {
    return execute(new RedisCallback() {
      @Override
      public Object doWithRedis(Jedis jedis) {
        return redisConfig.getSerializer().unserialize(jedis.hget(id.getBytes(), key.toString().getBytes()));
      }
    });
  }

  @Override
  public Object removeObject(final Object key) {
    return execute(new RedisCallback() {
      @Override
      public Object doWithRedis(Jedis jedis) {
        return jedis.hdel(id, key.toString());
      }
    });
  }

  @Override
  public void clear() {
    execute(new RedisCallback() {
      @Override
      public Object doWithRedis(Jedis jedis) {
        jedis.del(id);
        return null;
      }
    });

  }

  @Override
  public ReadWriteLock getReadWriteLock() {
    return readWriteLock;
  }

  @Override
  public String toString() {
    return "Redis {" + id + "}";
  }

  public void setTimeout(Integer timeout) {
    this.timeout = timeout;
  }

}

3,总结


主要就是实现了 putObject getObject clear 等方法,把缓存处理下。
其中需要 配置 针对 insert update delate flushCache=“true” 做强制刷新缓存。
然后针对多表关联数据,就没有办法了。useCache=“false” 禁用 cache就行了。
这样在redis 这样的集中式缓存中可以部署多个 tomcat 实例不影响缓存更新了。
主要是使用 hset 实现的。同时增加了超时时间。针对整个大key。

本文的原文连接是:
https://blog.csdn.net/freewebsys/article/details/91410171

博主地址是:http://blog.csdn.net/freewebsys

发布了624 篇原创文章 · 获赞 259 · 访问量 208万+

猜你喜欢

转载自blog.csdn.net/freewebsys/article/details/91410171