mybatis3.5.6的cachekey

        mybatis有一级缓存和二级缓存,默认开启一级缓存;在查询的时候会先查缓存,缓存中没有数据才会查询数据库;那么是根据什么来确定当前要查询的数据已经在缓存中呢?一个叫cacheKey对象,可以确定前要查询的数据是否在缓存中。
        cacheKey和我们缓存的数据有什么联系呢?由于一条查询语句,会查询到相应的数据;所以会根据查询语句的sql还有其他的数据生成cacheKey作为键值,查询到的数据作为value保存到缓存中;这样就可以通过cachekey来获取缓存中的数据了。

源码分析

我们先看CacheKey的结构:


  private static final int DEFAULT_MULTIPLIER = 37;
  private static final int DEFAULT_HASHCODE = 17;
/**计算hashcode的乘积数默认:37*/
  private final int multiplier;
  /**hashcode默认17*/
  private int hashcode;
  private long checksum;
  private int count;
  private List<Object> updateList;
/**新建对象,初始化数据*/
  public CacheKey() {
    this.hashcode = DEFAULT_HASHCODE;
    this.multiplier = DEFAULT_MULTIPLIER;
    this.count = 0;
    this.updateList = new ArrayList<>();
  }

/**
*1.将参数object添加到uplist对象中
*2.计算hashcode,checksum,count
*
*/
  public void update(Object object) {
    int baseHashCode = object == null ? 1 : ArrayUtil.hashCode(object);

    count++;
    checksum += baseHashCode;
    baseHashCode *= count;

    hashcode = multiplier * hashcode + baseHashCode;

    updateList.add(object);
  }

/**
*比较cacheKey是否相等;
*主要是比较cacheKey的几个属性是否相等;
*
*
*
*/

  public boolean equals(Object object) {
    if (this == object) {
      return true;
    }
    if (!(object instanceof CacheKey)) {
      return false;
    }

    final CacheKey cacheKey = (CacheKey) object;

    if (hashcode != cacheKey.hashcode) {
      return false;
    }
    if (checksum != cacheKey.checksum) {
      return false;
    }
    if (count != cacheKey.count) {
      return false;
    }

    for (int i = 0; i < updateList.size(); i++) {
      Object thisObject = updateList.get(i);
      Object thatObject = cacheKey.updateList.get(i);
      if (!ArrayUtil.equals(thisObject, thatObject)) {
        return false;
      }
    }
    return true;
  }

cacheKey比较重要的2个方法:

  • update:生成cacheKey,主要是往uplist中填充值;
  • equals:比较2个key是否相等;判断cacheKey是否相等:主要是比较cacheKey的属性:hashcode ,checksum ,count ,updateList;

cacheKey如何生成(主要看uplist中填充了哪些值)?是BaseExcutor类中的方法createCacheKey:

  public CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql) {
    if (closed) {
      throw new ExecutorException("Executor was closed.");
    }
    CacheKey cacheKey = new CacheKey();
    cacheKey.update(ms.getId());
    cacheKey.update(rowBounds.getOffset());
    cacheKey.update(rowBounds.getLimit());
    cacheKey.update(boundSql.getSql());
    List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
    TypeHandlerRegistry typeHandlerRegistry = ms.getConfiguration().getTypeHandlerRegistry();
    // mimic DefaultParameterHandler logic
    for (ParameterMapping parameterMapping : parameterMappings) {
      if (parameterMapping.getMode() != ParameterMode.OUT) {
        Object value;
        String propertyName = parameterMapping.getProperty();
        if (boundSql.hasAdditionalParameter(propertyName)) {
          value = boundSql.getAdditionalParameter(propertyName);
        } else if (parameterObject == null) {
          value = null;
        } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
          value = parameterObject;
        } else {
          MetaObject metaObject = configuration.newMetaObject(parameterObject);
          value = metaObject.getValue(propertyName);
        }
        cacheKey.update(value);
      }
    }
    if (configuration.getEnvironment() != null) {
      // issue #176
      cacheKey.update(configuration.getEnvironment().getId());
    }
    return cacheKey;
  }

这个方法中可以看到一共调用update方法6次;

uplist: id+offset+limit+sql+parameterValue+environmentId

实际cachekey:
在这里插入图片描述

再分别解释一下uplist中数据的含义
id:全限定类名+方法名
offset:偏移量(默认:0)
limit:查询数据条数(默认:Integer.MAX_VALUE)
sql:查询语句
parameterValue:查询参数的值
environmentId:在配置mybatis环境的时候有一个标签:environment ,他有一个属性id;environmentId的就是这个id的值;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值