Mybatis自带二级缓存底层数据结构为HashMap,无法适用于分布式环境。
本文要点:
1.Mybatis整合Redis实现分布式缓存
2.查看自定义缓存实现类RedisCache及相关源码,了解Redis在实现MyBatis二级缓存中的执行工作流 (更多二级缓存知识点可参考MyBatis二级缓存),存储类型(hash)等
1. Mybatis整合Redis实现分布式缓存
A.引入Mybatis整合Redis依赖 Jar包
org.mybatis.caches
mybatis-redis
1.0.0-beta2
B.SqlMapConfig.xml中开启二级缓存
C.apper.xml中
D.resources下添加redis.properties文件,配置redis连接信息 (路径及命名强制要求为redis.properties,具体原因可见下面的源码分析)
redis.host=localhost
redis.port=6379
redis.connectionTimeout=5000
redis.password= redis.database=0
E.代码及执行后日志信息 (Mybatis日志信息开启需要在项目中配置log4j.properties,可参考MyBatis二级缓存中的配置,因为日志信息与实现了org.apache.ibatis.cache的类org.apache.ibatis.cache.decorators.LoggingCache相关)
第二次查询不执行SQL,控制台显示命中率为0.5;且在Redis中查看到相应的key value已生成
key= -604684758:1070847255:com.kay.dao.UserMapper.findById:0:2147483647:select * from user where id = ?:1:dev
@Test
public void testRedisLevelTwoSuccess(){
SqlSessionFactory sessionFactory = sqlSessionFactoryBuilder.build(resourceAsStream);
SqlSession sqlSession1 = sessionFactory.openSession();
SqlSession sqlSession2 = sessionFactory.openSession();
SqlSession sqlSession3 = sessionFactory.openSession(true);
UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);
UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);
UserMapper userMapper3 = sqlSession3.getMapper(UserMapper.class);
System.out.println("--------------执行SqlSession1创建的UserMapper1对象的查询---------------------");
User user1 = userMapper1.findById(1);
sqlSession1.close(); // 查询后关闭sqlSession1
System.out.println("--------------执行SqlSession2创建的UserMapper2对象的查询---------------------");
User user2 = userMapper2.findById(1);
System.out.println("两次查询出来的对象 user1 user2 是否相等 : " + (user1 == user2));
sqlSession1.close();
}
(由redis中生成的数据可知道 mybatis二级缓存在redis中存储方式为hash,且key为namespace,具体代码验证见下面源码分析部分)
2. .自定义缓存实现类RedisCache及相关源码
A.查看redis二级缓存实现类RedisCache源码 Mybatis在启动加载Mapper.xml文件时,会加载对应的RedisCache类,执行RedisCache的构造方法(传入的Id为Mapper文件的namesapce) 通过执行RedisConfig redisConfig = RedisConfigurationBuilder.getInstance().parseConfiguration();获取RedisConfig对象 ,并根据RedisConfig对象生成redis操作类JedisPool
B.RedisConfig为redis连接的基本信息实体类(该实体类初始化时赋予了默认值;故启动时,如果本地的redis配置为redis默认配置,那么不配置redis.properties也可以实现)
C.根据步骤A进入parseConfiguration()方法中,可见将配置文件都成流并封装到RedisConfig对象中读取的文件为System.getProperty("redis.properties.filename", "redis.properties") 是固定代码
===》》》》redis基本信息的配置文件必须放在resourcesc下并且名字必须为redis.properties
D.redis.properties中数据封装到RedisConfig对象中后,通过此RedisConfig创建JedisPool对象( A图中parseConfiguration下一步)
pool = new JedisPool(redisConfig, redisConfig.getHost(), redisConfig.getPort(), redisConfig.getConnectionTimeout(), redisConfig.getSoTimeout(), redisConfig.getPassword(), redisConfig.getDatabase(), redisConfig.getClientName());
E.查看RedisCache中的核心方法 putObject() getObject() 可知:Mybatis中的二级缓存在redis中是以Hash的方式存储的,key为RedisCache类下的属性id.getBytes(即为mapper.xml文件的namespace),name为二级缓存的key.getBytes,value为二级缓存value对象序列化后的值 (示例可见上文中redis生成的数据)
相关代码:https://gitee.com/sunshinekay/mybatis-practice.git