1. 文档简介
任何一个系统,一定存在 大量的查询 用于接口输出 以及 前端页面展示,如果 我们能够针对 【查询】场景进行梳理与分析,再此基础上进行一定的业务建模,形成研发团队 统一的【查询类】输出模式,这样一来,具有如下几个较好的优势:
1、整个 查询技术栈 统一维护与输出,可以按照版本不断的迭代
2、节约大量开发人员的工作量,开发人员仅仅按照指定的格式编写对应的配置文件 即可
3、查询输出的结果 具有自我描述性(查询结果含有元数据的描述 以及 部分前端展示需要的标识)
4、更加更加快速的响应产品需求方的诉求,快速迭代输出产品原型以及产品功能本身
1.1 写作目的
通过该对【查询场景】的描述,可以站在更高的一个角度来看待【查询】,同与实际的具体的业务场景相结合,更加有效的 迭代现有的【查询】功能,使其可更加灵活输出技术以及结果,给到前端或者接口方,满足不同业务场景的需求。
通过 该文档,我们 可以 了解到 独立编写 【查询引擎】的初衷与阶段性获取的效果,同时 也通过 本文针对【查询引擎】的概要设计,了解比较完备的设计思路,后期的详细设计可以按照该思路进行展开详述。
1.2 影响范围
该模块的输出 影响范围含
1、产品团队:如何基于【查询引擎】的思维角度,快速构建产品原型
2、研发团队:如何基于【查询引擎】实现当前的大部分的查询输出以及 如何迭代优化【查询引擎】,使其更加强大
3、前端团队:基于 【元数据】描述的【查询结果】,应该采用自动化的解析模式,完成数据的展示,不在依赖硬性代码的编写(例如 GRID,仪表盘等)
1.3 参考资料
[待完善]
1.4 名词解释
【元数据】:再本文中 【元数据】除了描述 字段本身的含义之外,还需要针对【前端组件】的展示需要,定义部分约定的属性定义,这些 属性定义也纳入 【元数据】定义的范畴,例如查询结果的 格式化展示等 % 输出等
【元数据驱动-查询引擎】:该 查询模式,再原有的基础上 输出结果 同时包含 针对该结果集的【元数据】的描述,可通过参数来决定查询结果是否返回【元数据】定义,抑或【查询结果】本身
1.5 阅读范围
2. 业务场景概述
2.1 【查询引擎】的业务定位
我们可以把业务系统分解为 两大体系构成:完成【业务操作】体系与【查询输出】体系
其中 他们定义分别如下:
【业务操作】:是指再程序中,完成某种必要的业务实现,例如 新增工厂、上轴、换品种 等 具有明确的业务含义
【查询输出】:是指 为了协助用户更好的理解与完成业务,我们需要把一些【业务模型】打散以及再装配,输出到【界面层】或者【接口层】,从而协助用户更好的实现期业务操作或者 报表展示等
所以,再本文中所要描述 展示 的 部分为 【查询输出体系】,而【业务操作体系】不在本文讨论的范围内。
2.2 【 查询引擎】作用范围
【查询】的目的从业务来讲很明显:就是更加直观的展现用户想要看到的结果。
【查询】的本质:则是从 简单或者复杂的 存储介质中 ,按照用户或者消费者 输入的条件 对实际的数据 进行再次筛选 以及 重新装备 的过程,最终把结果 通过某种【渠道】发送给 消费者自身。
通过上图 ,我们可以大致分解一个查询流程的整个数据流程:
【查询引擎】与业务模块 之间的关联关系
2.3、业务建模
按照上图的模型梳理,我们可以针对梳理的结果进行业务建模,该业务模型的基本组成如下:(按照经验,目前仅分享针对 关系型数据库 的模型),该模型为之前 公司已经实现的部分功能的展示(算是 抛砖引玉 ),作为一个个案进行分析:
1、该模型 含有 查询结果 的【元数据】描述模块
2、该模型 含有 具体执行SQL查询的 SQL语句模板
3、该模型 含有 SQL可支持的查询参数的 定义 与解析规则
4、该模型 含有 唯一的标识 便于外部程序定位
基于该业务模型的流程规则 重新定位如下:
其中 【唯一标识】:让消费者可以明确定位要执行查询的 查询模型
【查询条件与解析规则】:则是 再查询之前 对数据条件的 过滤与 解析 ,其中 含对 异常数据的过滤(不属于该SQL的查询条件 则会自动被过滤 ),
同时完成 条件的解析( 特别是再WEB场景模式下,输入基本都是 String 类型的入参,
通过解析 实现 【参数类型的转换 (String 转化为 各种JAVA 对应的类型)】,
【参数数据模型的转换】 针对 查询语句中 含有各种数据模板的解析,可适应于复杂的SQL模板 )
【SQL模板】:SQL模板则是 把解析的查询条件,通过【模板引擎】+【条件】进行装配,最终输出 JDBC 可识别的查询SQL(预编译的 SQL 等)
【元数据】:查询结果返回为,需要按照【元数据】的定义的模式,最一定的数据加工处理
最终 反馈给消费者 是 含有【元数据】定义与【查询结果】 组装再一起的 结果 的输出。
2.4、【查询模型】举例
如上图所示代码片段,该片段展示了【查询模型】的定义的主要格式: 该SQL配置 参考 ibaits 的SQL部分实现
1、【唯一ID】 modle.id + sql.id 确定 【查询模型】的唯一性
2、【元数据】定义 描述了 查询结果集 的数据定义 以及 其他定义(后文详述)
3、【查询条件以及解析规则】 定义 查询条件为String 类型,并且针对 该SQL数据是必须输入的项目 (其他输入条件则自动过滤)
4、【SQL模板】:作为 【条件】+【SQL模板】—》 【模板引擎】—》 JDBC 可识别的查询输入
2.5、【查询结果】输出
按照用户的请求,查询结果的输出 可分为如下场景:
1、仅输出 【元数据】模型,用于 渲染 页面等其他作用
2、输出 【元数据】+【查询结果】 其中【查询结果】分 LIST 与 PAGED
3、仅仅输出 【查询结果】
其中 【元数据】的描述,可于前端协商完成一些通用组件的解析定义,最终实现 以【元数据】驱动为主的 界面展示。
3 、代码举例
3.1 设计思路
整体架构如下所示:
解释:
1、【转换引擎】负责把 编写完毕的 文件进行加载以及转换(支持动态加载),基于Apache 下的 【commons-digester 】实现
2、【条件解析模块】 是对查询条件的统一建模于解析,支持 数据解析,时间范围、枚举 等
3、【SQL装配模块】基于Freemarker 实现,把条件+SQL模板 叠加渲染输出 JDBC 可识别的 预编译 的查询数据 ,预防SQL注入
4、【结果渲染模块】查询结果返回后,按照【元数据】的定义,增加 结果的元数据 描述信息,以及 一些 二次加工的过程(例如 二次汇总结果 等)
5、【查询结果】通过标准的 对 Java 模型 转换为 JSON 格式 输出前端
2.6、结果输出
接口描述: http://*********/domian/query/{model_id}/{sql_id}/map.json (单值输出)
http://*********/domian/query/{model_id}/{sql_id}/list.json (多值输出)
http://*********/domian/query/{model_id}/{sql_id}/page.json (分页输出)
4、模型详解
4.1 唯一标识
【唯一标识】作为唯一识别模型的索引,这一点 与 目前我司采用的Mybatis 类似,采用 双ID模式,实现定位 唯一查询引擎的唯一标识
4.2 元数据
【元数据】 是模型中比较复杂的内容一致,也是作为 【查询引擎】主要特性组成,【元数据】为数据定义了 多方面的展示模式:
1、数据 类型的描述
2、数据 展示方式的描述
3、作为特殊场景的数据 存储与输出
4、可按实际需要 任意扩展 元数据的定义 (更多需要 前端 解析达成一致 )
如下图展示比较复杂的【元数据】模型:
例如:基于上图的展示元数据:元数据定义了如下信息
1、每个【查询结果】列的 列名称标识 列名称中文 列名称描述 列类型 以及 前端展示需要格式化的类型: type="money"
2、定义了 如果作为 表格展示模式 那些列 是固定列 那些列是活动列:fixCol= true
等 ,实际该模型为 可扩展模型,除了你要的字段之外,其他的属性 则作为 read属性 直接注入,最终参与 前端的模型输出,对应后台并不做任何处理
4.3 查询条件
【查询条件】模型 不行封装了 SQL 可接受的参数列表与参数类型,同时还包含了 这些模型解析的数据结构。最终用于支持 多种类型的SQL输出:
例如 between and in 模型等
下图为 具体的例子
红色筐部分为查询条件输出区域:
1、定义数据类型 例如 可以是 单值、多值 以及 值类型
2、定义参数 是否为必填 参数
3、如果缺失 是否填充默认值 等
4.4 SQL模板
【SQL模板】 采用 Freemarker 作为SQL语句解析的 模板引擎,可以装配任意负责的 SQL 输出,以及 再内部自定义 变量等,之前的公司 不涉及 跨数据源的查询,仅仅针对SQL数据的查询,
查询 主要是 针对 Web请求 的查询实现
5、使用场景
上述分享了作为 【元数据-查询引擎】的一些内部规则以及基本得实现,而作为 最终使用该 查询引擎的程序员,需要关注那些点呢:
针对后台程序员:
1、XML 查询模型 配置规则
2、XML 查询模型 文件位置
3、代码调试
针对前端程序员:
1、调用的【查询模型】ID
2、【查询模型】传参
以上
6、不足地方
1、不支持 多个结果查询 结果的 叠加
2、多租户 模式下,需要扩展 更多的属性 支持 不同租户的个性化输出
3、不支持 多数据源 的结果叠加