书接上回,有两个解决方案
1 写一个类似spring cache的功能在service层做会话级缓存(微服务场景,全局缓存不行)
2 重新baseExecutor的query方法,在mybatis层面上加标签注明表,只刷新同表数据
最终选择了类似1的解决方案,用了ThreadLocal类,在线程内做一个缓存(参考 实现ThreadLocalContext管理线程变量),由于我的这个功能在单次请求内反复查询了多个表的数据,但是查询最多的表是有限的,并且我的系统分运行态和设计态,这张表是设计态的表,接口是运行接口设计表几乎不会修改,因此不考虑并发等问题。所以在这张表的查询接口上包了一个判断ThreadLocalContext.get(数据id)是否为空,不为空则直接返回,为空则入库查询并缓存。这种实现方案通用性较弱,但是整体成本低。
原接口是调用serviceImpl的getById,修改为
@Override
public AObject getById(Serializable idSer){
String id = (String)idSer;
AObject aObject = ThreadLocalContext.get(id);
if(aObject == null){
return baseMapper.selectById(id);
}else{
return aObject;
}
}
在原来的机制下,由于每次调用DML语句都会清空所有mybatis缓存,设计态的表被反复查询,整个接口的调用时长超过了一秒,优化后时间减半。
并且添加了一个ThreadLocalContextFilter,确保每次会话结束时缓存会被清空,如果没有这个类的话,很难把握数据初始化和清空的时机。