19°

#技术分享# 查询引擎的设计思路与落地

     在上一家公司的产品实施过程中,按照8/2原则,感觉多数的的业务访问都是基于CRUD中的R完成的,即通过简单抑或复杂的查询条件完成各式各样的操作操作,最终把结果展示在UI层,实现用户对查询结果预览等。结合(DDD)领域驱动模型CQRS架构风格,把业务高度抽象为Read与Wirte 两种模式,其中基于Read模式的实现 ,在系统开发的过程中分装了一个查询引擎,用的尚且不错,故把设计的一些思路分享给大家....  就怕贻笑大方。  废话少说,转入正题:话说那年冬天,天气蒙蒙亮,一个鬼影鬼魅般的出现在庭院中间......咳咳咳 严重跑题了。

      针对Read查询业务,按照业务的驱动,应该具备如下的一些业务诉求:

      1、查询引擎的SQL是面向JDBC的,用户可快速编写SQL同时可对SQL进行不断的优化(这里区别于 基于 一些 ORM框架 例如 JPA )

      2、编辑后的SQL文件可热加载,整个过程无需重启服务器(文件包含 新增、删除、修改等) 这是针对SQL文件而言

      3、引擎支持分页查询,用户无需查询两次后去结果在进行装配结果(SQL语句还是自己编写  -- 亦可自动生成 )

      4、支持多样性的查询条件装配以及防止SQL注入

      5、支持查询结果的元数据描述以及数据结果的自动格式化操作,前端拿到无需在此渲染可直接展示,减少对UI的二次加工

      6、支持并发查询,并对结果集汇总,到了JDK8的时代,不搞点并发并发的特性在上面,真的对不起该引擎了

      7、查询条件的格式化处理,查询引擎直接对接UI层,界面层传递的数据我们可假定为字符串,而实际数据却类型迥异,需要在注入之前 格式化为指定的配型 

      8、LOG输出可调节,按照debug,info等输出不同的日志信息,可远观亦可亵玩。。。。 并能对查询时间进行统计 (是否持久化那是后话)

       上述几条基本涵盖了查询引擎的主要业务需求,经过展开分析以及归纳,结合我本人多年的开发经验,最终采用 XML+Freemarker 配合完成,在这里不考虑换数据库的情况(实际业务投产后 鲜有换数据库的情况,就算有,就让他发生把...换库的问题不在本次业务需求范围内),其中XML作为结构化的语言定义整个引擎的建模,Freemarker 主要实现动态SQL的输出,与Mybitis比较功能上更为强大,毕竟是Freemarker 是专业的模板引擎(性能问题如何解决,我已经全部基于Freemarker Cache了所有的模板,并且跟踪了调用的次数,Guava Cache  自带功能 SQL每次执行的耗时情况等)。如下是部分的代码片段,先给出XML的配合Demo,如下仅为参考(查询引擎代码  暂无): 强大的宏定义 也是我推荐采用Freemerker 的强项,可以节约大量重复的SQL编写输出。

<sql id="list_unit_label_statistics" dynamic="true">
			 <meta>
				<col id="unit_name" name="单位名称" desc="单位名称" type="str" fixed="true" freeze="true"/>
				 <col id="unit_oldid" name="单位编号" desc="单位编号" type="str"  freeze="true"/>
				<col id="unit_id" name="单位ID" desc="单位ID" type="hidden"/>
				<col id="searchtime_type" name="查看维度" desc="查看维度" type="str" />
				<col id="total_num" name="总会员数" desc="总会员数" type="str" />
				<col id="begin_time" name="开始时间" desc="开始时间" type="str" />
				<col id="end_time" name="结束时间" desc="结束时间" type="str" />
				<col id="labeled_members" name="已打标签会员" desc="已打标签会员" type="str" />
				<col id="percent_0_20" name="0-20%占比" desc="0-20%占比" type="str" />
				<col id="percent_21_40" name="21%-40%占比" desc="21%-40%占比" type="str" />
				<col id="percent_41_60" name="41%-60%占比" desc="41%-60%占比" type="str" />
				<col id="percent_61_80" name="61%-80%占比" desc="61%-80%占比" type="str" />
				<col id="percent_81_100" name="81%-100%占比" desc="81%-100%占比" type="str" />
			 </meta>
            <body><![CDATA[
          SELECT   .......
          【可编写基于Freemerkaer 】 为基础的 模块代码,通过FReemarker模板渲染,输出最终的可配查询因引擎识别的SQL  语句
            ]]></body>
        </sql>

 

        用户通过Restful的网址直接定位 http://******:8080/restful/[查询夫ID]/[SQLID]/[list,map,page].json  完成不同查询结果的输出。结果回顺带范围查询结果的元数据描述以及针对部分数据直接进行格式化处理,便于前端展示,例如  金额、日期等可在后台直接转换为标准类型输出。

       技术无好坏,只是是否在恰当的时候引用了该技术.........在家休闲时间,打算把这块代码从现有的代码框架中剥离出来,传输到Github上,不知道能得到多少点赞~~~ 算是无聊事件下  聊以自慰的手段把。

      尽情期待............待续

 

 

 

 

 

 

本文由【边缘行者】发布于开源中国,原文链接:https://my.oschina.net/qfhxj/blog/3136605

全部评论: 0

    我有话说: