热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Mybatis一级缓存的锅

问题背景项目开发中有一个树形数据结构,不像经典组织结构树、菜单级别树,我们这个树形结构是用户后期手动建立起来的关系。因此数据库表结构为两张表:数据记录表、记录关系表,通过业务规则限

问题背景


项目开发中有一个树形数据结构,不像经典组织结构树、菜单级别树,我们这个树形结构是用户后期手动建立起来的关系。因此数据库表结构为两张表:数据记录表、记录关系表,通过业务规则限制,形成的树形结构像下面这样:


特殊之处就是树结构节点是有重复的



  • 不复制重复节点

    5NVrIU.png



  • 复制重复节点



5NVDaT.png

项目要求前端展示、导出时使用复制重复节点的方式。开搞吧


Mybatis树结构查询

树结构查询,在mysql下当然是使用Mybatis框架提供的递归查询了。



  1. xml配置文件











  1. mapper文件

public interface OKRAlignExportMapper {
TreeNode getTree(Long objectiveId);
}


  1. 查询结果

5NVyiF.png


树结构导出到Excel

关于树形结构数据导出,我参考这篇博客,并针对OKR的特点做了修改。

Java 树形结构数据生成导出excel文件

OKR对齐视图数据结构的特点是:



  • 1.以本人的目标为中心,向左右两侧发散。

  • 2.左侧是自己对齐的目标,以及对齐目标再次对齐的目标,递归到顶。

  • 3.右侧是向自己对齐的目标,递归到底。

关于OKR对齐视图这种数据结构的导出,我们下篇博客会把完整的代码放上来,并分析一下。这里说一下导出这种树形结构数据的主要步骤:



  • 1.计算每条数据的行列坐标,这里采用递归的算法,最终可以计算出父级节点需要合并的行数,以及Excel文件的最大列数。

  • 2.根据行列坐标递归输出每条数据的值到Excel单元格。


Mybatis一级缓存导致的问题

首先我们来了解一下Mybatis一级缓存:


Mybatis对缓存提供支持,但是在没有配置的默认情况下,它只开启一级缓存,一级缓存只是相对于同一个SqlSession而言。所以在参数和SQL完全一样的情况下,我们使用同一个SqlSession对象调用一个Mapper方法,往往只执行一次SQL,因为使用SelSession第一次查询后,MyBatis会将其放在缓存中,以后再查询的时候,如果没有声明需要刷新,并且缓存没有超时的情况下,SqlSession都会取出当前缓存的数据,而不会再次发送SQL到数据库。


mybatis一级缓存二级缓存

由于Mybatis的缓存机制,导致在出现重复的叶子节点时,虽然树结构正常构建,但是指向的是同一个java对象。因为是使用的Mybatis的递归查询,因此确认整个查询在一个SqlSession中执行完成,肯定是一级缓存导致的。这样会造成的后果,就是无法设置重复叶子节点的正确位置,因为指向同一个java对象,后遍历到的节点设置会覆盖前面的节点设置。


解决方案

既然确定是一级缓存导致的,那关闭或者清除一级缓存就行了吧。因为是框架的递归查询,因此无法

调用SqlSession的修改、添加、删除、commit(),close等清空一级缓存。那怎么办呢,笨办法了:

既然树的结构关系时正确的,只是重复节点指向了同一个java对象,那就遍历重建对象吧

/**
* 深度拷贝树结构
* @param node
* @return
*/
private static OKRAlignTreeNode deepCopyTree(OKRAlignTreeNode node){
OKRAlignTreeNode newNode = node.clone();
List children = node.getChildren();
if(children!=null&&children.size()>0){
List newChildren = new LinkedList<>();
for (OKRAlignTreeNode child:children){
if(child!=null){
OKRAlignTreeNode newChild = deepCopyTree(child);
newChildren.add(newChild);
}
}
newNode.setChildren(newChildren);
}
return newNode;
}


推荐阅读
author-avatar
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有