jfinal分页查询动态SQL的高级处理应用实例,解决你繁琐的查询条件拼接问题!

       因为在项目实践中有的时候SQL查询条件会有十几个甚至几十个的情况;如果只用正常的sql拼接方式的需要编写大量的if elseif 来判断查询条件是否为空,以及进行拼接。

        运用jfinal的SQL模版文件方式后代码量降低了80%。

        SQL模版文件使用#namesapce与#include 指令对其它模板文件进行统一管理。

        业务层使用getSqlPara(String key, Object… paras)的方式,入参使用 Kv.by的方式。

以下是一个简单的代码实例:

业务层代码;

/**
 * 描述:(获取用户列表接口)
 * 作者:${xf}
 
 * 参数: pageSize,startIndex,userType...可以是几十个参数
 * 创建:${2017-05-03} ${13:00:00}
 */
@Override
public Ret listUser(Record param) {
    int pageSize = Integer.parseInt(String.valueOf(param.get("pageSize")));
    int pageNum = Integer.parseInt(String.valueOf(param.get("startIndex")));
    param.remove("pageSize").remove("startIndex");
    Map map = param.getColumns();
    Kv queryParam = Kv.by("age>", ageOne).set("age<",ageTwo).set(map);
    SqlPara sqlPara = Db.getSqlPara("customer.listUser",Kv.by("queryParam", queryParam));
    Page<Record> page =Db.paginate(pageNum, pageSize, sqlPara);
    return ReturnMessage.gsonPage(page);
}

模版SQL

all_sqls文件统一管理所有sql文件:

#namespace("customer")
#include("customer.sql")
#end

customer.sql文件:

#sql("listUser")
select userName,phone, userType from test_user
 #for(param:queryParam)
 #(for.index==0? "where" : "and" ) #field(param.key)#para(param.value) 
 #end
#end

#field方式需要自己增加一个扩展指令处理模版SQL中的查询条件的 where a=1 and b<

package com.sanqimei.www.common.kit;
import java.io.Writer;
import com.jfinal.template.Directive;
import com.jfinal.template.Env;
import com.jfinal.template.stat.CharTable;
import com.jfinal.template.stat.Scope;
public class FieldDirective extends Directive {
public void exec(Env env, Scope scope, Writer writer) {
        String key = exprList.eval(scope).toString().trim();
        write(writer, key);
        if (CharTable.isLetterOrDigit(key.charAt(key.length() - 1))) {
            write(writer, " = ");
        }
    }
}

然后在config中引入arp.getEngine().addDirective("field", new FieldDirective());


评论区

JFinal

2017-05-06 17:07

越来越多人发现 sql 管理功能的高级玩法了,感谢分享

昵称而已

2017-05-08 11:14

all_sqls是一个什么文件?放在哪? 有demo地址吗?

JFinal

2017-05-08 12:34

@昵称而已 all_sqls 就是一个普通的文本文件,起什么名字都可以,扩展名也可以任意,通常建议用 .sql 为扩展名

JFinal

2017-05-08 12:35

@昵称而已 补充一句, alls_sqls 的这种用法在 jfinal 3.1 手册中有一小节专门讲了,可以了解一下

xf1951495330

2017-05-08 20:27

@昵称而已 文件名称自己定义,只是对不同业务sql文件统一管理引用的汇总文件,你可以想下config里路由的分模块管理

guaifeng

2017-05-09 14:27

程序代码中不应该出现和数据库相关的信息才对,实现有些不够优雅

tonysb

2017-05-11 17:26

楼主你好,Kv queryParam = Kv.by("age>", ageOne).set("age<",ageTwo).set(map);中set(map)这个是起什么作用的?

焱121121

2017-05-12 10:22

@JFinal 什么时候出书啊?赶紧出本书。

xf1951495330

2017-05-12 16:35

@tonysb 绑定查询条件的作用

欲风217

2017-05-12 17:48

@xf1951495330 建议写成这样的(感谢 @小徐同学 提供),兼容 value 为空的情况。
select * from test_user where 1=1
#for(x:cond)
#if(x.value != null && x.value != "")
and #field(x.key) #para(x.value)
#end
#end
order by #(sort) #(order)

JFinal

2017-05-12 18:14

@欲风217 #if(x.value != null && x.value != "") 可以做如下改进:
#if(x.value && x.value != "")

jfinal 对于逻辑运算进行了简化, if( value != null) 等价于 if ( value ),因为 if (null) 为 false

JFinal

2017-05-12 18:15

@欲风217 注意看手册中有关逻辑表达式的规则,在总体上保留 java 规则的前提下,进行了有利于用户体验的改进

小鱼@

2017-05-17 14:57

好东西

xf1951495330

2017-05-27 14:38

@欲风217 你要加判断的话#if(x.value) #end 即可,

欲风217

2017-06-16 16:59

2222222

2017-07-17 18:10

请问一下kv.by()和kv.set()有什么区别?

JFinal

2017-07-17 18:46

@2222222 Kv.by 是静态方法,在创建 kv 对象的同时置入一个 key value 值,而 Kv.set 仅仅只是置入值,并不会创建 kv 对象,只要用一下就知道区别了

zhpingjfinal3.1

2017-08-10 10:43

@JFinal 请教一下,多条件查询,like 模糊查询 日期的>= <=,而且还要兼容value为空的情况,这个怎么写,有例子吗?

xf1951495330

2017-09-05 14:52

@zhpingjfinal3.1 #if(startPayTime)
AND DATE_FORMAT(a.payTime, '%Y-%m-%d') >= #para(startPayTime)
#end
#if(endPayTime)
AND DATE_FORMAT(a.payTime, '%Y-%m-%d') <= #para(endPayTime)
#end

xialinlin

2017-10-27 09:01

没法兼容 in

suxiaoqiuking

2017-12-07 14:42

这样能防止sql注入的情况?

suxiaoqiuking

2017-12-07 14:43

@JFinal 这种方式怎么能不能防止sql注入的情况

suxiaoqiuking

2017-12-07 14:56

很好用 感谢分享

JFinal

2017-12-07 17:36

@suxiaoqiuking 必然可以,因为参数用的 #para(...) 指令,只要是用到这个指令,都会生成问号占位,天然防注入

热门分享

扫码入社