关于Sql 管理与动态生成使用中遇到的问题

select * from usertable where status = ?
and username = ? and sex = ?

上面的SQL是经常写的,有时字段多了需要写很多and  xxx = ? 这样的,有时and的条件是不固定的。

在Jfinal3.0里支持了Sql 管理与动态生成,手册中给出的例子是

select * from table where status = #(statusOK)
#for(cond:condMap)
    and cond = #p(cond)
#end

例子中的condMap应该是个字符串数组,用下面的参数测试了下结果是

JMap map = JMap.create();
map.put("status", 1);
String[] cond ={"username","sex"};
map.put("condMap", cond);
Sql: 
select * from table where status = ?
and cond = ?
and cond = ?

Para: 
[1, username, sex]

感觉手册里的例子是否不对这样好像没什么意义。我想得到的应该是

Sql: 
select * from table where status = ?
and username = ?
and sex = ?

Para: 
[1, zhangsan, 男]

改变了姿势再试了下

SQL模板:

Select * from table where status = #p(status)
#for(cond:condMap)
    and #(cond) = #p(cond)
#end

JAVA代码:

JMap map = JMap.create();
map.put("status", 1);
map.put("username", "zhangsan");
map.put("sex", "man");

JMap condMap = JMap.create();
String[] cond ={"username","sex"};
map.put("condMap", cond);

得到的结果:

Sql: 
select * from table where status = ?
and username = ?
and sex = ?

Para: 
[1, username, sex]

参数对了,但是值不对。看来#p好像不支持动态的参数。

评论区

JFinal

2017-02-23 18:41

你是第一个发现 #p 指令只支持 identify 的,这个 p 指令已经删掉了对表达式类型的限制,如果你加入了俱乐部可以找我要最新的代码,如果没加入,去 jfinal 官方群里找我

JFinal

2017-02-23 18:45

有一个非常典型的用法是,传入的条件参数是 map 型,而生成 where 条件的时候,直接对 map 进行迭代,大致是这样的:

select * from table where status = #(statusOK)
#for(cond:condMap)
and #(cond.key) = #p(cond.value)
#end

注意上面的指令,and 后面的第一个是在用输出指令#()输出 map 中的属性名,后面的 #p 指令是将 map 中的属性值放入 paraList 中,并输出一个问号字符 '?' ,这样就起来就完全没阻碍了

rapin

2017-02-23 18:58

@JFinal 其实之前我试过了这样会报错。com.jfinal.template.stat.ParseException: the parameter of #p or #para directive must be identifier
-----------------------------------------------------------
JMap map = JMap.create();
map.put("status", 1);

JMap condMap = JMap.create();
condMap.put("username", "zhangsan");
condMap.put("sex", "man");

map.put("condMap", condMap);

dao.getSqlPara("testSql",map);
----------------------------------------------------------
在没有发行的版本已经支持了?

JFinal

2017-02-23 20:18

@rapin 在发布新版本后写新版本文档时发现了这个需求,在没有发行的版本已经支持了,放开了对 #p 指令参数类型的判断

以前对 #p 指令的参数类型判断严格是为了避免开发者传入错误的数据库类型造成错误,没注意到 #p(map.value) 这种需求的存在

JFinal

2017-02-24 10:54

@rapin 用上昨天发给你代码以后全搞定了吧?

rapin

2017-02-24 17:00

@JFinal 搞定,完美~:-)

JFinal

2017-02-24 17:31

@rapin 写个分享哈,贴点代码出来就好,在分享频道写: http://jfinal.com/share

wendell620

2017-03-02 20:44

@rapin 求分享,现在也遇到了这个问题

JFinal

2017-03-02 20:53

@wendell620 你自己也可以改进,将 ParaDirective 中的 setExprList 这个方法删掉就可以了

板砖哥

2017-03-06 18:53

@JFinal the parameter of #p or #para directive must be identifier #(cond.key) = #p(cond.value) 感谢

JFinal

2017-03-06 19:34

@板砖哥 jfinal 3.1 才可以让 p 指令这样来用: #p(cond.key),目前你先用一个 #set 指令过渡一下,这样用:
#set(key = cond.key, value = cond.value)
#p(key) #p(value)

板砖哥

2017-03-09 09:59

@JFinal 不好意思只能发这,反馈的已提交直接报错,测试了下这里可以发送