Mybatis源码分析(七)自定义缓存、分页的实现

一、缓存

我们知道,在Mybatis中是有缓存实现的。分一级缓存和二级缓存,不过一级缓存其实没啥用。因为我们知道它是基于sqlSession的,而sqlSession在每一次的方法执行时都会被新创建。二级缓存是基于namespace,离开了它也是不行。有没有一种方式来提供自定义的缓存机制呢?

1、Executor

Executor是Mybatis中的执行器。所有的查询就是调用它的 <E>List<E>query()方法。我们就可以在这里进行拦截,不让它执行后面的查询动作, 直接从缓存返回。

在这个类里面,我们先获取参数中的缓存标记和缓存的Key,去查询Redis。如果命中,则返回;未命中,接着执行它本身的方法。

@Intercepts({@Signature(method = "query", type = Executor.class,args = {

       MappedStatement.class,Object.class,RowBounds.class,ResultHandler.class})})

//BeanFactoryAware是Spring中的接口。目的是获取jedisService的Bean

public class ExecutorInterceptor implements Interceptor,BeanFactoryAware{
   private JedisServiceImpl jedisService;
   @SuppressWarnings("unchecked")
   public Object intercept(Invocation invocation) throws Throwable {
       if (invocation.getTarget() instanceof CachingExecutor) {
           //获取CachingExecutor所有的参数
           Object[] params = invocation.getArgs();
           //第二个参数就是业务方法的参数
           Map<String,Object> paramMap = (Map<String, Object>) params[1];
           String isCache = paramMap.get("isCache").toString();
           //判断是否需要缓存,并取到缓存的Key去查询Redis
           if (isCache!=null && "true".equals(isCache)) {
               String cacheKey = paramMap.get("cacheKey").toString();
               String cacheResult = jedisService.getString(cacheKey);
               if (cacheResult!=null) {
                   System.out.println("已命中Redis缓存,直接返回.");
                   return JSON.parseObject(cacheResult, new TypeReference<List<Object>>(){});
               }else {
                   return invocation.proceed();
               }
           }
       }
       return invocation.proceed();
   }
   //返回代理对象
   public Object plugin(Object target) {
       if (target instanceof Executor) {
           return Plugin.wrap(target, this);
       }
       return target;
   }
   public void setProperties(Properties properties) {}
   public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
       jedisService = (JedisServiceImpl) beanFactory.getBean("jedisServiceImpl");
   }
}

以上方法只是从缓存中获取数据,但什么时候往缓存中添加数据呢?总不能在每个业务方法里面调用Redis的方法,以后如果把Redis换成了别的数据库,岂不是很尴尬。

回忆一下Mybatis执行方法的整个流程。在提交执行完SQL之后,它是怎么获取返回值的呢?

2、ResultSetHandler

没有印象吗?就是这句 returnresultSetHandler.<E>handleResultSets(ps);其中的resultSetHandler就是DefaultResultSetHandle

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值