一次动态sql查询订单数据的设计

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一次动态sql查询订单数据的设计相关的知识,希望对你有一定的参考价值。

    订单数据一般是变化比较多的数据,查询条件也是比较复杂,如果没有一个规则解释,写接口的变动就会比较频繁;由于个人不喜欢在业务端使用拼接sql的方式,另外本身是做安全出身,业务端的sql拼接容易sql注入,所以不考虑使用;为了满足这个特性,将订单的条件进行了一次划分: 状态、用户、时间、公司、上车地点、下车地点;

    第一步: 先处理状态查询, 状态查询定义在t_om_group表中,后台人员可以手动添加状态分组,前端业务只需要状态分组对应哪些状态即可;如:

    group_id 1 对应 order_staus (1001,1002,1003)

    group_id 对应 order_status(1002,1003)

    第二步: 处理用户,用户有两个 driver 和 passenger, 这里当成参数输入,-1表示不验证

BEGIN

DECLARE sqlPattern VARCHAR(255);
DECLARE sqlTemp VARCHAR(1024);
DECLARE sqlExec VARCHAR(1024);
DECLARE sqlCondi VARCHAR(1024);

Select pattern into sqlPattern from t_om_group where group_id=groupId;

IF driverUid >= 0 AND passengerUid>=0 THEN
SET sqlCondi = CONCAT("driver_uid=", driverUid, " AND passenger_uid=", passengerUid);
ELSEIF driverUid<0 AND passengerUid>=0 THEN
SET sqlCondi = CONCAT("passenger_uid=", passengerUid);
ELSEIF driverUid>=0 AND passengerUid<0 THEN
SET sqlCondi = CONCAT("driver_uid=", driverUid);
ELSE
SET sqlCondi = "";
END IF;

IF sqlPattern=‘‘ OR sqlPattern IS NULL THEN
IF sqlCodi = "" THEN
set sqlTemp = "Select * from v_order";
ELSE
SET sqlTemp = CONCAT("Select * from v_order where", sqlCondi);
END IF;

ELSE
IF sqlCondi = "" THEN
SET sqlTemp = CONCAT("Select * from v_order where ", sqlPattern);
ELSE
SET sqlTemp = CONCAT("Select * from v_order where ", sqlCondi, " and ", sqlPattern);
END IF;

END IF;

SET @sqlExec=sqlTemp;
prepare stmt from @sqlExec;
EXECUTE stmt;
deallocate prepare stmt;

END

    第三步: 组装sql并执行,也就是动态sql

    第四步: 调用存储过程;

@Select("call sp_getGroupOrders(#{groupId}, #{driverUid}, #{passengerUid})")
@Options(statementType = StatementType.CALLABLE)
List<Map<String, Object>> getGroupOrders(@Param("groupId") Integer groupId,
@Param("driverUid") Integer driverUid,
@Param("passengerUid") Integer passengerUid);

    上面就完成第一个阶段的设计,动态查询数据;

    当然,这不是我们最终需要的,因为在实际使用过程中还会有更多的条件设置;我们需要查询进行一次定义;

    1, 哪些字段可以进行条件查询

    2, 业务是否传递该字段的值

    3,字段支持哪些表示式

这里我们就需要参考Mybaits的Example的设计了,但为了支持查询安全和动态sql,我们仍然需要将sql的查询与我们在t_om_group配置的条件进行一次匹配,然后再根据输入的参数进行查询处理;

    例如: group 验证规则为:   order_status in (${statusList}) and start_time>${startTime} and end_time<${endTime} 

那么解释sql时,就只处理这个三个参数定义值,那么同时要求业务端必须传递这三个参数,否则不执行查询;

    若按照上面的规则来处理,那么我们在处理查询的同时还可定义到t_om_order之外的表,下面来来设计这个查询规则表:

    group_id:编号 group_name:名称 table_name:表名 fields:字段列表 where_expr:条件表达式 order_expr:排序表达式 group_expr: 分组表达式

    sql模板: select ${fields} from ${table_name} where ${where_expr} order by ${order_expr} group by ${group_expr}

   验证参数 : 如果配置了where_expr, 通过拦截处理 where_expr中的动态参数,参数不匹配则查询失败;匹配成功则执行查询;

 

   第二阶段完成,基本动态sql询就可以了;

   第三阶段: 多表和嵌套查询,未完待续 

 

以上是关于一次动态sql查询订单数据的设计的主要内容,如果未能解决你的问题,请参考以下文章

SQL动态列查询

如何用FastReport制作动态报表

根据气流中 sql 查询的结果创建动态任务

mybatis 动态SQL查询总结

T-SQL 动态 SQL 和临时表

动态SQL(章节摘要)