JFinal

登录 注册

自定义指令实现sql语句中对in的问号拼接

测试效果:
     public static void main(String[] args) {
        String sqlTemplate = "select * from t_gril where sex = #para(sex) and age in (#paraIn(age)) and name = #para(name)";
         Kv cond = Kv.create()
                 .set("sex", 1)
                 .set("name", "dddd")
                 .set("age", "18,19");
         SqlPara sp = getSqlPara(sqlTemplate, cond);
//         String sqlTemplate = "select * from t_gril where sex = #para(0) and age in (#paraIn(1)) and name = #para(2)";
//         SqlPara sp = getSqlPara(sqlTemplate, 1,"18,19","ddde");
         log.debug(sp.getSql());
         log.debug(sp.getPara()[3]+"");
     }

结果输出:

DEBUG - select * from t_gril where sex = ? and age in (?,?) and name = ?
DEBUG - dddd


原码

public class ParaInDirective extends Directive {

    /**
     * 描述:
     */
    private int index = -1;

    /**
     * 描述:
     * 
     * @author Robin Zhang
     * @created 2017年7月7日 下午2:57:23
     * @param exprList
     * @see com.jfinal.template.Directive#setExprList(com.jfinal.template.expr.ast.ExprList)
     */
    public void setExprList(ExprList exprList) {
        if (exprList.length() == 1) {
            Expr expr = exprList.getExpr(0);
            if (expr instanceof Const && ((Const) expr).isInt()) {
                index = ((Const) expr).getInt();
                if (index < 0) {
                    throw new ParseException("The index of para array must greater than -1", location);
                }
            }
        }
        this.exprList = exprList;
    }

    /**
     * 描述:
     * 
     * @author Robin Zhang
     * @created 2017年7月7日 下午2:57:31
     * @param env
     * @param scope
     * @param writer
     * @see com.jfinal.template.stat.ast.Stat#exec(com.jfinal.template.Env,
     *      com.jfinal.template.stat.Scope, java.io.Writer)
     */
    public void exec(Env env, Scope scope, Writer writer) {
        SqlPara sqlPara = (SqlPara) scope.get("_SQL_PARA_");
        if (sqlPara == null) {
            throw new TemplateException("#paraIn invoked by getSqlPara(...) method only", location);
        }
        StringBuffer inPlaceholder = new StringBuffer();
        String valueStr = "";
        if (index == -1) {
            Expr[] exprArray = exprList.getExprArray();
            Object ret = null;
            for (Expr expr : exprArray) {
                boolean hasPara = scope.getData().containsKey(expr.toString());
                if (hasPara) {
                    ret = expr.eval(scope);
                    if (ret==null) {//in类的参数值不可为空
                        throw new TemplateException(
                                "The value of parameter '"+expr.toString()+"' must not be null",
                                location);
                    }
                } else {//没有传参数抛异常
                    throw new TemplateException(
                            "The parameter '"+expr.toString()+"' must be define",
                            location);
                }
            }
            valueStr = String.valueOf(ret);
//            sqlPara.addPara(exprList.eval(scope));
        } else {
            Object[] paras = (Object[]) scope.get("_PARA_ARRAY_");
            if (paras == null) {
                throw new TemplateException(
                        "The #paraIn(" + index + ") directive must invoked by getSqlPara(String, Object...) method",
                        location);
            }
            if (index >= paras.length) {
                throw new TemplateException("The index of #paraIn directive is out of bounds: " + index, location);
            }
            valueStr  = String.valueOf(paras[index]);
//            sqlPara.addPara(paras[index]);
        }
        Object[] retArrray = valueStr.split(",");
        for (int i = 0; i < retArrray.length; i++) {
            inPlaceholder.append("?");
            if (i != retArrray.length - 1) {
                inPlaceholder.append(",");
            }
            sqlPara.addPara(retArrray[i]);
        }
        write(writer, inPlaceholder.toString());
    }
}

注册paraIn指令:

Engine.addDirective("paraIn", new ParaInDirective());

评论

  • 08-26 15:50
    指令扩展又玩出了新意,超赞
  • 08-26 15:59
    看到你的扩展指令中需要使用 SqlKit.SQL_PARA_KEY 这类常量,jfinal 3.3 考虑将这些常量弄成 public 的,便于这类扩展
  • 08-26 16:31
    @JFinal 其实我自己不是用SqlKit.SQL_PARA_KEY 我自己用自己的常量了。只是发出来时改成这个了。没注意看这个不是public的。我改下
  • 08-27 09:29
    @JFinal 3.3建议加个动态URL的指令
  • 08-27 14:22
    @北流家园网 具体需求是什么样的? 知道了需求才知道怎么添加这个 url 指令
  • 08-28 16:34
    @JFinal 可以写个扩展指令 #renderUrl ,大致如下:
    1:创建 RenderUrlDirective extends Directive
    2:内部用一个 String content = HttpKit.get(url) 先获取url 指向的数据
    3: ret = engine.getTemplateByString(content).renderToString() 得到渲染结果
    4:通过 writer.write(ret) 将结果输出即可
  • 08-28 16:45
    @北流家园网 这个扩展为啥还需要 getTemplateByString(...) 这一步呢? 直接 writer.write(content) 不就可以了?

    要知道从一个 url 过来的 content 之中如果有恶意代码,在使用模板引擎渲染的时候有危险性,当然这个危险性极小,因为 jfinal 模板引擎默认对很多操作已经做了屏蔽
  • 08-28 17:14
    @JFinal 这4点是你之前回复我的,但我还是不懂如何写。
  • 发送