适用于JFinal的一个SQL Select和SqlExceptSelect的生成器

247 篇文章 1 订阅
16 篇文章 0 订阅

最近学习别人的代码熟悉系统,发现其SQL语句写得那叫一个丑,全篇的if else,满屏的String相加。我根据以前汤阳光老师的hibernate的QueryHelper,针对JFinal的特点,写了一个辅助生成SQL语句的类。可以动态添加条件或者排序条件,使用起来非常优雅。

以下是代码和示例性使用代码:

/**
 * 
 * 调用方式】 QueryHelper helper = new QueryHelper(Reply.class, "r")//
 * .addCondition("r.topic=?", topic)// .addOrderProperty("r.postTime", true);
 * 
 * PageBean pageBean = replyService.getPageBean(pageNum, pageSize, helper);
 * 或者添加condition和orderby之后直接调用preparePageBean
 */
/**
 * 
 * 用于生成 select .... 必须select,from前面的 需要查找哪些字段,如果全部就用*表示
 * 
 * 用于生成sqlExceptSelect from ... 必须 哪个表 where 可选 条件1 and 条件2 and ... 条件n brder by
 * 可选 属性1, 属性2, ... 属性n 用于辅助拼接SQL语句
 * 
 * 
 * 支持方法连缀 生成select和sqlExceptSelect语句 $生成参数列表$ $生成查询总记录数的SQL,去除掉OrderBy$
 * 
 * @author 熊诗言 StringBuffer代替String应该还能提升性能
 */
public class QueryHelper{


    private String       select;                                  // select语句
    private String       fromClause;                              // from子句
    private StringBuffer whereClause   = new StringBuffer("");    // where子句
    private StringBuffer orderByClause = new StringBuffer("");    // order by子句


    private List<Object> parameters    = new ArrayList<Object>(); // 参数列表


    /**
     * 用于一张表的情况,生成From子句
     * 
     * from topic t
     */
    public QueryHelper(String select, String tableName, String alias){
        this.select = select;
        fromClause = new StringBuffer(" from ").append(tableName).append(" ").append(alias).toString();
    }


    /**
     * 用于left join 这种可以写在一个from字句中
     */
    public QueryHelper(String select, String from){
        this.select = select;
        fromClause = new StringBuffer(" from ").append(from).toString();
    }


    /**
     * 用于两张表联合的情况,生成From子句,类似from table1 a,table2 b 然后添加where条件
     * 这个方法的调用格式为("select...","table1","alias1","table2","alias2"...),至少两对,
     * 如果只有一个表, 那就按照第一个构造方法调用 。后面的表和别名是一对一对出现的
     */
    public QueryHelper(String select, String[] table_alias){
        if(table_alias.length <= 2 || table_alias.length % 2 != 0){
            throw new RuntimeException("你的参数有误,请看该方法的说明");
        }
        this.select = select;
        StringBuffer buffer = new StringBuffer(" from ");


        int group = table_alias.length / 2;// 有这么多个表
        for(int i = 0; i < group; i++){
            buffer.append(table_alias[i * 2]).append(" " + table_alias[i * 2 + 1]).append(",");
        }
        buffer.deleteCharAt(buffer.length() - 1);
        fromClause = buffer.toString();
    }


    /**
     * 拼接where子句 d.id between ? and ? d.parent=? d.parent is null
     * 
     * @param condition
     * @param params
     */
    public QueryHelper addCondition(String condition, Object... params){
        // 拼接
        if(whereClause.length() == 0){
            whereClause = new StringBuffer(" where ").append(condition);
        } else{
            whereClause.append(" and ").append(condition);
        }


        // 参数
        if(params != null){
            for(Object p : params){
                parameters.add(p);
            }
        }


        return this;
    }


    /**
     * 如果第一个参数为true,则拼接where子句
     * 
     * @param append
     * @param condition
     * @param params
     */
    public QueryHelper addCondition(boolean append, String condition, Object... params){
        if(append){
            addCondition(condition, params);
        }
        return this;
    }


    /**
     * 拼接order by子句
     * 
     * @param propertyName
     *            参与排序的属性名
     * @param asc
     *            true表示升序,false表示降序
     */
    public QueryHelper addOrderProperty(String propertyName, boolean asc){
        if(orderByClause.length() == 0){
            orderByClause = new StringBuffer(" order by ").append(propertyName + (asc ? " asc" : " desc"));
        } else{
            orderByClause.append(", ").append(propertyName + (asc ? " asc" : " desc"));
        }
        return this;
    }


    /**
     * 如果第一个参数为true,则拼接order by子句
     * 
     * @param append
     * @param propertyName
     * @param asc
     */
    public QueryHelper addOrderProperty(boolean append, String propertyName, boolean asc){
        if(append){
            addOrderProperty(propertyName, asc);
        }
        return this;
    }


    public String getSelect(){
        return this.select;
    }


    /**
     * 获取生成的用于查询数据列表的sqlExceptSelect语句
     * 
     * @return
     */
    public String getSqlExceptSelect(){
        // 这里面含有一些?,下面来填充
        String sqlExceptSelect = new StringBuffer(fromClause).append(whereClause).append(orderByClause).toString();
        // 填充参数
        if(parameters != null){ // 设置参数
            for(int i = 0; i < parameters.size(); i++){
                // 巧妙利用替换一次之后,后面的?就自动往前移动一位,那么replaceFirst每次替换的就是下一个?
                sqlExceptSelect = sqlExceptSelect.replaceFirst("\\?", "'" + parameters.get(i) + "'");
            }
        }
        return sqlExceptSelect;
    }


    /**
     * 获取生成的用于查询总记录数的SQL语句
     * 
     * @return
     */
    public String getCountQuerySql(){
        return "select count(*) " + fromClause + whereClause;
    }


    /**
     * 获取SQL中的参数值列表
     * 
     * @return
     */
    public Object[] getParameters(){
        return parameters.toArray();
    }


    /**
     * 获取生成的用于查询数据列表的sqlExceptSelect语句,里面可能含有?,需要配合getParameters
     * 
     * @return
     */
    public String getSqlExceptSelectWithPadding(){
        // 这里面含有一些?,下面来填充
        String sqlExceptSelect = new StringBuffer(fromClause).append(whereClause).append(orderByClause).toString();
        return sqlExceptSelect;
    }

    public static void main(String[] args){
        QueryHelper helper = new QueryHelper("select a.*,b.*", "table1 a", "table2 b");
        helper.addCondition("a.parentId=b.id");
        System.out.println(helper.getSelect());
        System.out.println(helper.getSqlExceptSelect());


        ConcurrentHashMap<String, String> searchInfo = new ConcurrentHashMap<String, String>();
        searchInfo.put("name", "颜色");


        QueryHelper helper2 = SkuService.service.getQueryHelper(searchInfo);
        System.out.println(helper2.select + helper2.getSqlExceptSelectWithPadding());
    }
}



SkuService.service.getQueryHelper(searchInfo)的代码如下

public QueryHelper getQueryHelper(ConcurrentHashMap<String, String> searchInfo){
        QueryHelper helper = new QueryHelper("select k.id,k.name,s.user_name as operated_by,k.operated_time,k.enabled",
                "sku k left join sys_user s on k.operated_by=s.id")//
                        .addCondition(searchInfo.containsKey("name"),
                                      "(k.name like ? or k.id in (select o.sku_id from sku_opt o where o.name like ?))",
                                      "%" + searchInfo.get("name") + "%", "%" + searchInfo.get("name") + "%")
                        .addCondition("k.enabled=?", 1)//
                        .addOrderProperty("k.operated_time", false);

        return helper;
    }


getSqlExceptSelectWithPadding方法,该方法是含有?填充符的,为了防SQL注入,需配合getParameters方法。其实getSqlExceptSelect也是将?替换为参数值,应该也能防注入。这两种方式的区别是前者是PrepareStatement来替换?,后者先替换再传给PrepareStatement,可能前者的效率高些。

感谢汤阳光老师。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值