订单数据一般是变化比较多的数据,查询条件也是比较复杂,如果没有一个规则解释,写接口的变动就会比较频繁;由于个人不喜欢在业务端使用拼接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询就可以了;
第三阶段: 多表和嵌套查询,未完待续