Mybatis缓存和Redis缓存服务器的案例分析

MyBatis默认是支持一级缓存和二级缓存,他自身的实现是通过PerpetualCache,这哥缓存对象实现了,当然也可以是MemarCache。目前中用的比较多的就是Redis,是一个nosql数据库,也称为缓存数据库。


1. 什么是一级缓存? 为什么使用一级缓存?

      每当我们使用MyBatis开启一次和数据库的会话,MyBatis会创建出一个SqlSession对象表示一次数据库会话

      在对数据库的一次会话中,我们有可能会反复地执行完全相同的查询语句,如果不采取一些措施的话,每一次查询都会查询一次数据库,而我们在极短的时间内做了完全相同的查询,那么它们的结果极有可能完全相同,由于查询一次数据库的代价很大,这有可能造成很大的资源浪费。

      为了解决这一问题,减少资源的浪费,MyBatis会在表示会话的SqlSession对象中建立一个简单的缓存,将每次查询到的结果结果缓存起来,当下次查询的时候,如果判断先前有个完全一样的查询,会直接从缓存中直接将结果取出,返回给用户,不需要再进行一次数据库查询了。

     如下图所示,MyBatis会在一次会话的表示----一个SqlSession对象中创建一个本地缓存(local cache),对于每一次查询,都会尝试根据查询的条件去本地缓存中查找是否在缓存中,如果在缓存中,就直接从缓存中取出,然后返回给用户;否则,从数据库读取数据,将查询结果存入缓存并返回给用户。



这个图很好的说明了MyBatis一级缓存的使用周期,以及过程。


Mybatis一级缓存的工作过程:

1.对于某个查询,根据statementId,params,rowBounds来构建一个key值,根据这个key值去缓存Cache中取出对应的key值存储的缓存结果;

2. 判断从Cache中根据特定的key值取的数据数据是否为空,即是否命中;

3. 如果命中,则直接将缓存结果返回;

4. 如果没命中:

        4.1  去数据库中查询数据,得到查询结果;

        4.2  将key和查询到的结果分别作为key,value对存储到Cache中;

        4.3. 将查询结果返回;

5. 结束。


接下来是和Redis整合的例子:

Redis可以说是第三方缓存数据库,很强大,这样就会涉及到二级缓存,二级缓存的图如下:



继承Cache接口:

[html]  view plain  copy
  1. package com.lgy.cache;  
  2.   
  3. import java.util.concurrent.locks.ReadWriteLock;  
  4. import java.util.concurrent.locks.ReentrantReadWriteLock;  
  5.   
  6. import org.apache.ibatis.cache.Cache;  
  7. import org.slf4j.Logger;  
  8. import org.slf4j.LoggerFactory;  
  9.   
  10. import com.lgy.util.SerializeUtil;  
  11. import com.lgy.util.redis.JedisPoolUtils;  
  12.   
  13. import redis.clients.jedis.Jedis;  
  14.   
  15.   
  16. public class MybatisRedisCache implements Cache {  
  17.   
  18.     private static Logger logger = LoggerFactory.getLogger(MybatisRedisCache.class);  
  19.     private Jedis redisClient = JedisPoolUtils.getPool().getResource();  
  20.     /** The ReadWriteLock. */  
  21.     private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();  
  22.   
  23.     private String id;  
  24.   
  25.     public MybatisRedisCache(final String id) {  
  26.         if (id == null) {  
  27.             throw new IllegalArgumentException("Cache instances require an ID");  
  28.         }  
  29.         logger.debug(">>>>>>>>>>>>>>>>>>>>>>>>MybatisRedisCache:id=" + id);  
  30.         this.id = id;  
  31.     }  
  32.       
  33.     @Override  
  34.     public String getId() {  
  35.         return this.id;  
  36.     }  
  37.       
  38.     @Override  
  39.     public int getSize() {  
  40.         return Integer.valueOf(redisClient.dbSize().toString());  
  41.     }  
  42.   
  43.     @Override  
  44.     public void putObject(Object key, Object value) {  
  45.         logger.debug(">>>>>>>>>>>>>>>>>>>>>>>>putObject:" + key + "=" + value);  
  46.         redisClient.set(SerializeUtil.serialize(key.toString()), SerializeUtil.serialize(value));  
  47.     }  
  48.       
  49.     @Override  
  50.     public Object getObject(Object key) {  
  51.         Object value = null;  
  52.         byte[] bs = redisClient.get(SerializeUtil.serialize(key.toString()));  
  53.         if(bs != null) {  
  54.             value = SerializeUtil.unserialize(bs);  
  55.         }  
  56.         logger.debug(">>>>>>>>>>>>>>>>>>>>>>>>getObject:" + key + "=" + value);  
  57.         return value;  
  58.     }  
  59.       
  60.     @Override  
  61.     public Object removeObject(Object key) {  
  62.         logger.debug(">>>>>>>>>>>>>>>>>>>>>>>>removeObject:key=" + key);  
  63.         return redisClient.expire(SerializeUtil.serialize(key.toString()), 0);  
  64.     }  
  65.   
  66.     @Override  
  67.     public void clear() {  
  68.         logger.debug(">>>>>>>>>>>>>>>>>>>>>>>>clear");  
  69.         redisClient.flushDB();  
  70.     }  
  71.   
  72.     @Override  
  73.     public ReadWriteLock getReadWriteLock() {  
  74.         logger.debug(">>>>>>>>>>>>>>>>>>>>>>>>getReadWriteLock");  
  75.         return readWriteLock;  
  76.     }  
  77.   
  78. }  

 注意几个特别的方法:

1.getObject

2.putObject

3.clear

1.第一次调用select语句时候

               a.会执行getObject()方法,从缓存中获取,若获取到了直接返回。

               b.活执行getObject()方法,从缓存中获取,为null则会执行select sql语句,然后调用putObject方法将key-value存在缓存服务器中。

2.调用update语句,会清空db,调用clear方法

Mybatis实现缓存的机制使用了大量的装饰者模式,有兴趣同学可以去研究下!

转载于:https://blog.csdn.net/qq383264679/article/details/49798807

备注:https://blog.csdn.net/qq_25689397/article/details/52066179,这篇文章通过源码分析更加详情的讲解了mybatis中整合redis


  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值