/**
*
* 拼接Where的指令,较简单的where组装,如果复杂的请在模版直接写where 语句
* @author xianyl
* @since 2018年1月26日-下午8:57:02
*/
public class WhereDirective extends Directive {
//运算符号集合、逻辑符号集合、between条件集合,字段名
public static final String KV_SIGNS = "kv_signs";
public static final String KV_LOGICS = "kv_logics";
public static final String KV_BETWEEN = "kv_between";
public void exec(Env env, Scope scope, Writer writer) {
SqlPara sqlPara = (SqlPara)scope.get("_SQL_PARA_");//SqlKit.SQL_PARA_KEY 需要跟它一致
if (sqlPara == null) {
throw new TemplateException("#where directive invoked by getSqlPara(...) method only", location);
}
//获取参数
Map<String, Object> data = null;
Kv signs = null, logics = null, between = null;
try {
Record record = (Record)exprList.eval(scope);
data = record.getColumns();
signs = (Kv) data.remove(KV_SIGNS);
logics = (Kv) data.remove(KV_LOGICS);
between = (Kv) data.remove(KV_BETWEEN);
} catch (Exception e) {
}
//判断参数不能为null 并且只能是Record
if(MapUtils.isEmpty(data)) return;
StringBuilder sb = new StringBuilder();
//循环拼接参数
Object logic;
Object sign;
for(Entry<String, Object> d : data.entrySet()){
Object _end = null;
//判断逻辑符号
if(logics == null){
logic = LogicsSymbol.And;//没有逻辑符号集合,这是and
}else{
logic = logics.get(d.getKey());
if(logic == null){
logic = LogicsSymbol.And;//没有对应字段的逻辑符号,这是and
}
}
//判断运算符号
if(signs == null){
sign = SignsSymbol.Eq;//没有运算符号集合,这是eq
}else{
sign = signs.get(d.getKey());
if(sign == null){
//没有对应字段的运算符号,这是eq
sign = SignsSymbol.Eq;
}
if(sign == SignsSymbol.Between){
//如果是between运算符号,需要检查between里面的field_end的数据取出
_end = between == null ? null : between.get(d.getKey() + "_end");
}
}
//拼接条件
this.join(sb,sqlPara,d.getKey(),d.getValue(),logic,sign,_end);
}
//写where
write(writer, sb.toString());
}
/**
* 拼接其中一个条件语句
* @param sb
* @param sqlPara
* @param key 字段名
* @param value 字段值
* @param logic 逻辑符号
* @param sign 运算符号
* @param _end between时字段的第二个值
*/
private void join(StringBuilder sb, SqlPara sqlPara, String key, Object value, Object logic, Object sign, Object _end) {
//第一时间判断_end 是否为null, 如果是 SignsSymbol.Between 转成 SignsSymbol.Gte
if(sign == SignsSymbol.Between && _end == null){
sign = SignsSymbol.Gte;
}
//拼接逻辑符号
if(sb.length() == 0){
if(logic == LogicsSymbol.And){
sb.append(" where ");
}else{
sb.append(" where 1=1 ").append(logic);
}
}else{
sb.append(" ").append(logic);
}
//拼接参数
sb.append(" ").append(key).append(" ").append(sign).append(" ").append("?");
sqlPara.addPara(sign == SignsSymbol.Like ? "%"+value+"%" :value);
if(sign == SignsSymbol.Between){
//如果between
sb.append(" and ").append("?");
sqlPara.addPara(_end);
}
}
}
模版 : #namespace("user") #sql("list") select * from user #where(data) #end #end java调用方法: /** * 根据模板动态生成 sql 跟参数 * @param key 模板名 namespace.sql * @param record 查询条件 键值对 * @param signs 运算符号集合 {"field":SignsSymbol.Gt} , 如果没有,则为Eq * @param logics 逻辑符号集合 {"field":LogicsSymbol.And}, 如果没有,则为Or * @param between between条件集合 {"field_end":value}, signs为between时检查这个,如果没有指定的field_end,则转为Gte运算符号 * @return */ public SqlPara getSqlPara(String key, Record data, Kv signs, Kv logics, Kv between){ //这几个字段名需要跟WhereDirective里面的对应起来 data.set(WhereDirective.KV_SIGNS, signs); data.set(WhereDirective.KV_LOGICS, logics); data.set(WhereDirective.KV_BETWEEN, between); //data跟sql模版的参数对应起来 return Db.getSqlPara(key, Kv.by("data", data)); }
* 指令被解析时注入指令参数表达式列表,继承类可以通过覆盖此方法对参数长度和参数类型进行校验
*/
public void setExprList(ExprList exprList) {
this.exprList = exprList;
}
请问这个方法的使用场景是什么?它只有项目启动的时候才会触发一次啊。