您的位置:首页 > 数据库

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

2016-06-15 00:00 519 查看
摘要: 适用于JFinal的一个SQL Select和SqlExceptSelect的生成器

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

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());
}

}

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

感谢汤阳光老师。

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

public QueryHelper getQueryHelper(ConcurrentHashMap<String, String> searchInfo){
System.out.println(searchInfo.containsKey("name"));
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息