当前位置: 首页 > 工具软件 > mybatis-redis > 使用案例 >

myBatis整合redis

高山
2023-12-01

redis分布式缓存,mybatis提供了一个针对cache接口的redis实现类,该类存在mybatis-redis包 中

  1. pom文件
   <dependency>
      <groupId>org.mybatis.caches</groupId>
      <artifactId>mybatis-redis</artifactId>
      <version>1.0.0-beta2</version>
   </dependency>

2.配置文件
Mapper.xml 添加上

 <cache type="org.mybatis.caches.redis.RedisCache" />

3.redis.properties
redis.host=localhost
redis.port=6379
redis.connectionTimeout=5000
redis.password= redis.database=0
以上整合完事

相关源码分析:

public final class RedisCache implements Cache {
    private final ReadWriteLock readWriteLock = new DummyReadWriteLock();
    private String id;
    private static JedisPool pool;

    public RedisCache(String id) {
        if (id == null) {
            throw new IllegalArgumentException("Cache instances require an ID");
        } else {
            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启动的时候,由MyBatis的CacheBuilder创建,创建的方式很简单,就是调用
RedisCache的带有String参数的构造方法,即RedisCache(String id);而在RedisCache的构造方法中,
调用了 RedisConfigurationBuilder 来创建 RedisConfig 对象,并使用 RedisConfig 来创建JedisPool。

RedisConfig类继承了 JedisPoolConfig,并提供了 host,port等属性的包装,简单看一下RedisConfig的
属性

public class RedisConfig extends 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;

RedisConfig对象是由RedisConfigurationBuilder创建的,简单看下这个类的主要方法:

	public RedisConfig parseConfiguration(ClassLoader classLoader) {
		Properties config = new Properties();
		InputStream input = classLoader.getResourceAsStream(redisPropertiesFilename);
		if (input != null) {
			try {
				config.load(input);
			} catch (IOException e) {
				throw new RuntimeException(
						"An error occurred while reading classpath property '"
								+ redisPropertiesFilename
								+ "', see nested exceptions", e);
			} finally {
				try {
					input.close();
				} catch (IOException e) {
					// close quietly
				}
			}
		}
		RedisConfig jedisConfig = new RedisConfig();
		setConfigProperties(config, jedisConfig);
		return jedisConfig;
	}

核心的方法就是parseConfiguration方法,该方法从classpath中读取一个redis.properties文件
host=localhost
port=6379
connectionTimeout=5000
soTimeout=5000
password= database=0
clientName=

并将该配置文件中的内容设置到RedisConfig对象中,并返回;接下来,就是RedisCache使用 RedisConfig类创建完成jedisPool;

接下来看看Cache中最重要的两个方法:putObject和getObject,通过这两个方法来查看mybatis-redis
储存数据的格式:

    public void putObject(final Object key, final Object value) {
        this.execute(new RedisCallback() {
            public Object doWithRedis(Jedis jedis) {
                jedis.hset(RedisCache.this.id.toString().getBytes(), key.toString().getBytes(), SerializeUtil.serialize(value));
                return null;
            }
        });
    }
    @Override
    public Object getObject(final Object key) {
        return execute(new RedisCallback() {
            @Override
            public Object doWithRedis(Jedis jedis) {
                return SerializeUtil.unserialize(jedis.hget(id.toString().getBytes(), key.toString().getBytes()));
            }
        });
    }

RedisCache中实现了一个简单的模板方法,用来操作Redis

    private Object execute(RedisCallback callback) {
        Jedis jedis = pool.getResource();
        Object var3;
        try {
            var3 = callback.doWithRedis(jedis);
        } finally {
            jedis.close();
        }
        return var3;
    }

实现doWithRedis方发

public interface RedisCallback {
	Object doWithRedis(Jedis jedis);
}

可以很清楚的看到,mybatis-redis在存储数据的时候,是使用的hash结构,把cache的id作为这个hash
的key (cache的id在mybatis中就是mapper的namespace);这个mapper中的查询缓存数据作为 hash
的field,需要缓存的内容直接使用SerializeUtil存储,SerializeUtil和其他的序列化类差不多,负责 对象的
序列化和反序列化;

 类似资料: