项目中为了使项目的数据库操作从dao层转移到service层,只好写一个通用的sql语句拼接类和相应的mapper类和mapper的xml文件,自定义的SelectBuilder.java的代码如下:
- import java.io.IOException;
- import java.util.ArrayList;
- import java.util.List;
-
- import com.util.StringHelper;
-
- /**
- * SelectBuilder:SQL条件拼接类,该类只做sql语句的拼接
- * @author LMH 修改
- * @notice 注意:为了用好该类,必须熟悉掌握sql语句完整语法
- * @SQLGrammar SELECT语句的完整语法为:
- *SELECT[ALL|DISTINCT|DISTINCTROW|TOP] <br/>
- *{*|talbe.*|[table.]field1[AS alias1][,[table.]field2[AS alias2][,…]]} <br/>
- *FROM tableexpression[,…][IN externaldatabase] <br/>
- *[WHERE…] <br/>
- *[GROUP BY…] <br/>
- *[HAVING…] <br/>
- *[ORDER BY…] <br/>
- *[WITH OWNERACCESS OPTION] <br/>
- *说明: <br/>
- *用中括号([])括起来的部分表示是可选的,用大括号({})括起来的部分是表示必须从中选择其中的一个。 <br/>
- *
- */
- public class SelectBuilder
- {
- private static final String AND = ")
AND (";
-
- private static final String OR = ")
OR (";
-
- List<String> select = new ArrayList<String>();
-
- List<String> from = new ArrayList<String>();
-
- List<String> join = new ArrayList<String>();
-
- List<String> innerJoin = new ArrayList<String>();
-
- List<String> outerJoin = new ArrayList<String>();
-
- List<String> leftOuterJoin = new ArrayList<String>();
-
- List<String> rightOuterJoin = new ArrayList<String>();
-
- List<Criterion> where = new ArrayList<Criterion>();
-
- List<Criterion> having = new ArrayList<Criterion>();
-
- List<String> groupBy = new ArrayList<String>();
-
- List<String> orderBy = new ArrayList<String>();
-
- List<String> lastList = new ArrayList<String>();
-
- boolean distinct;
-
- /**
- * 设置SQL语句中从select到from的部分
- * @param conditons 查詢的内容,可以写字段,聚合函数等
- * @example 参数例子:" table1.id as id,table2.mc as mc ",
- * @notice 注意:如果要查询的字段名有相同的,必须用as **的方式进行区分,不然会不能正确set进hashmap里
- *
- */
- public void SELECT(String conditons)
- {
- select.add(conditons);
- }
- /**
- * 设置SQL语句中从select distinct到from的部分,可以写字段,聚合函数等
- * @param columns 查詢的字段列表
- * @example 参数例子:" table1.id as id,table2.mc as mc ",
- * @notice 注意:如果要查询的字段名有相同的,必须用as **的方式进行区分,不然会不能正确set进hashmap里
- *
- */
- public void SELECT_DISTINCT(String columns)
- {
- distinct = true;
- SELECT(columns);
- }
-
- /**
- * 设置SQL语句中从from到where的部分
- * @param table: 表名列表,可以是要查询的表名列表,或者直接加上join连接
- * @example 参数例子:" table1 " 或者" table1,table2 "
- */
- public void FROM(String table)
- {
- from.add(table);
- }
- /**
- * 设置JOIN连接条件 <br/>
- * 切记用了join相关的链接,则form里只能有一个表,而且,join函数之后,后面不得再加from函数
- * @param join:JOIN连接条件,由3部分组成:表名 别名 + on +连接条件
- * @example join参数例子:" bmd_mss b on b.bmd_h=loc.x_h "
- */
- public void JOIN(String join)
- {
- this.join.add(join);
- }
- /**
- * 设置INNER_JOIN连接条件 <br/>
- * 切记用了join相关的链接,则form里只能有一个表,而且,join函数之后,后面不得再加from函数
- * @param join:INNER_JOIN连接条件,由3部分组成:表名 别名 + on +连接条件
- * @example join参数例子:" bmd_mss b on b.bmd_h=loc.x_h "
- */
- public void INNER_JOIN(String join)
- {
- innerJoin.add(join);
- }
- /**
- * 设置LEFT_OUTER_JOIN连接条件
- * 用了join相关的链接,则form里只能有一个表,而且,join之后,后面不得再加form函数
- * @param join:LEFT_OUTER_JOIN连接条件,由3部分组成:表名 别名 + on +连接条件
- * @example join参数例子:" bmd_mss b on b.bmd_h=loc.x_h "
- */
- public void LEFT_OUTER_JOIN(String join)
- {
- leftOuterJoin.add(join);
- }
- /**
- * 设置RIGHT_OUTER_JOIN连接条件
- * 用了join相关的链接,则form里只能有一个表,而且,join之后,后面不得再加form函数
- * @param join:RIGHT_OUTER_JOIN连接条件,由3部分组成:表名 别名 + on +连接条件
- * @example join参数例子:" bmd_mss b on b.bmd_h=loc.x_h "
- */
- public void RIGHT_OUTER_JOIN(String join)
- {
- rightOuterJoin.add(join);
- }
- /**
- * 设置OUTER_JOIN连接条件
- * 用了join相关的链接,则form里只能有一个表,而且,join之后,后面不得再加form函数
- * @param join:OUTER_JOIN连接条件,由3部分组成:表名 别名 + on +连接条件
- * @example join参数例子:" bmd_mss b on b.bmd_h=loc.x_h "
- */
- public void OUTER_JOIN(String join)
- {
- outerJoin.add(join);
- }
-
- //为了适应动态参数而重写的where方法(没有参数的情况)
- /**
- *设置where子语句(一个参数的情况)
- * @param conditions: 连接条件,没有传动态参数的查询条件部分<br/>
- * 一个静态查询条件必须包含4部分内容:连接规则 字段列 运算符 值 <br/>
- * 连接规则: (and 或者 or)<br/>
- * 字段名: (field1)<br/>
- * 运算符: 必须以下运算符中的一个( > 或者 >= 或者 < 或者 <= 或者 <br/>
- * = 或者 <> 或者!= 或者 like 或者 not like 或者 in 或者 not in <br/>
- * 或者 between 或者 not between ) <br/>
- * 值 : 注意:如果元素符是in,则值部分必须写成 (value1,value2...)的形式。<br/>
- * 如果元素符是between,则值部分必须为 value1 and value2 的形式,value1为min,value2为max。<br/>
- * 如果元素符是like,则值部分可以在值的左右两边加上%或者_的通配符。<br/>
- * %:表示匹配任意个字符;_:表示匹配一个字符。<br/>
- * @example conditions参数例子:" and table1.id=table2.id or table1.mc=table2.mc and table1.id like "%1%" "
- */
- public void WHERE(String conditions)
- {
- if(StringHelper.isNotBlank(conditions))
- where.add( new Criterion(conditions));
- }
- //为了适应动态参数而重写的where方法,(单个参数或者in的情况)
- /**
- * 设置where子语句(两个参数的情况)支持单个参数或者in的情况
- * @param conditions: 连接条件,没有传动态参数的查询条件部分,必须包含3部分内容:<br/>
- * 连接规则:(and 或者 or)+ 字段列:(field1)+ 运算符 <br/>
- * 运算符:必须以下运算符中的一个( > 或者 >= 或者 < 或者 <= 或者 = 或者 <br/>
- * <> 或者!= 或者 like 或者 not like 或者 in 或者not in ) <br/>
- * @param value: 参数值,Object对象,支持任何类型<br/>
- * 注意:如果conditions的运算符是in, 则value部分可以传递一个list的对象,<br/>
- * list对象至少要包含一个Object类型的元素;如果conditions的运算符是like<br/>
- * 部分,则value部分可以在"value1"值的左右两边加上%或者_的通配符。<br/>
- * %:表示匹配任意个字符;_:表示匹配一个字符<br/>
- * @example conditions参数例子:" and table1.id= " 或者" and table1.id like "
- */
- public void WHERE(String conditions,Object value)
- {
- if(value!=null) //如果非空
- {
- if (value instanceof List<?>) //如果为list
- {
- if(!((List)value).isEmpty() ) //如果list非空
- where.add( new Criterion(conditions,value));
- }
- else //如果为其他直接添加
- where.add( new Criterion(conditions,value));
- }
- }
- //为了适应动态参数而重写的where方法(单个参数或者in的情况),有close关闭符号的情况
- /**
- * 设置where子语句(三个参数的情况)支持单个参数或者in的情况,有close关闭符号的情况
- * @param conditions: 连接条件,没有传动态参数的查询条件部分,必须包含3部分内容:<br/>
- * 连接规则:(and 或者 or)+ 字段列:(field1)+ 运算符 <br/>
- * 运算符:必须以下运算符中的一个( > 或者 >= 或者 < 或者 <= 或者 <br/>
- * = 或者 <> 或者!= 或者 like 或者 not like 或者 in 或者 not in ) <br/>
- * @param value: 参数值,Object对象,支持任何类型<br/>
- * 注意:如果conditions的运算符是in, 则value部分可以传递一个list的对象,list对象至少要包含一个Object类型的元素<br/>
- * 如果conditions的运算符是like部分,则value部分可以在"value1"值的左右两边加上%或者_的通配符<br/>
- * %:表示匹配任意个字符;_:表示匹配一个字符<br/>
- * @example conditions参数例子:" and table1.id= " 或者" and table1.id like "
- * @param close: 关闭符号,只有在处理or条件的时候才会用到,其他时候设置null或者""
- */
- public void WHERE(String conditions,Object value,String close)
- {
- if(value!=null) //如果非空
- {
- if (value instanceof List<?>) //如果为list
- {
- if(!((List)value).isEmpty() ) //如果list非空
- where.add( new Criterion(conditions,value,close));
- }
- else //如果为其他直接添加
- where.add( new Criterion(conditions,value,close));
- }
- }
- //为了适应动态参数而重写的where方法(between的情况),有close关闭符号的情况
- /**
- * 设置where子语句(四个参数的情况)支持between的情况,有close关闭符号的情况
- * @param conditions: 连接条件,没有传动态参数的查询条件部分,必须包含3部分内容:<br/>
- * 连接规则:(and 或者 or)+ 字段列:(field1)+ 运算符 <br/>
- * 运算符:必须以下运算符中的一个( between 或者 not between )<br/>
- * @param value: 参数值,Object对象,between的参数值左部分,支持任何类型<br/>
- * @param secondValue 参数值,Object对象,between的参数值右部分,支持任何类型<br/>
- * @example conditions参数例子:" and table1.id= " 或者" and table1.id like "
- * @param close: 关闭符号,只有在处理or条件的时候才会用到,其他时候设置null或者""
- */
- public void WHERE(String conditions,Object value,Object secondValue,String close)
- {
- if(value!=null&&secondValue!=null)
- where.add( new Criterion(conditions,value,secondValue,close));
- }
-
- /**
- * 设置分组字段列表
- * 切记GROUP_BY里面的字段select里面的字段必须有,不然会触发sql语法错误异常
- * @param columns: 分组字段
- * @example columns参数例子:"table1.id,table2.mc "
- */
- public void GROUP_BY(String columns)
- {
- groupBy.add(columns);
- }
-
-
- //为了适应动态参数而重写的having方法(没有参数的情况)
- /**
- *
- * 设置having子语句(一个参数的情况)<br/>
- * 切记having里面的字段group by里面必须有,不然会触发sql语法错误异常<br/>
- * @param conditions: 连接条件,没有传动态参数的查询条件部分<br/>
- * 一个静态查询条件必须包含4部分内容:连接规则 字段列 运算符 值 <br/>
- * 连接规则: (and 或者 or)<br/>
- * 字段名: (field1)<br/>
- * 运算符: 必须以下运算符中的一个( > 或者 >= 或者 < 或者 <= 或者 <br/>
- * = 或者 <> 或者!= 或者 like 或者 not like 或者 in 或者 not in <br/>
- * 或者 between 或者 not between ) <br/>
- * 值: 注意:如果元素符是in,则值部分必须写成 (value1,value2...)的形式。<br/>
- * 如果元素符是between,则值部分必须为 value1 and value2 的形式,value1为min,value2为max。<br/>
- * 如果元素符是like,则值部分可以在值的左右两边加上%或者_的通配符。<br/>
- * %:表示匹配任意个字符;_:表示匹配一个字符。<br/>
- * @example conditions参数例子:" and table1.id=table2.id or table1.mc=table2.mc and table1.id like "%1%" "
- */
- public void HAVING(String conditions)
- {
- if(StringHelper.isNotBlank(conditions))
- having.add( new Criterion(conditions));
- }
- //为了适应动态参数而重写的having方法(单个参数或者in的情况)
- /**
- * 设置having子语句(两个参数的情况)支持单个参数或者in的情况<br/>
- * 切记having里面的字段group by里面必须有,不然会触发sql语法错误异常<br/>
- * @param conditions: 连接条件,没有传动态参数的查询条件部分,必须包含3部分内容:<br/>
- * 连接规则:(and 或者 or)+ 字段列:(field1)+ 运算符 <br/>
- * 运算符:必须以下运算符中的一个( > 或者 >= 或者 < 或者 <= 或者 = 或者 <br/>
- * <> 或者!= 或者 like 或者 not like 或者 in 或者not in ) <br/>
- * @param value: 参数值,Object对象,支持任何类型<br/>
- * 注意:如果conditions的运算符是in, 则value部分可以传递一个list的对象,<br/>
- * list对象至少要包含一个Object类型的元素;如果conditions的运算符是like<br/>
- * 部分,则value部分可以在"value1"值的左右两边加上%或者_的通配符。<br/>
- * %:表示匹配任意个字符;_:表示匹配一个字符<br/>
- * @example conditions参数例子:" and table1.id= " 或者" and table1.id like "
- */
- public void HAVING(String conditions,Object value)
- {
- if(value!=null) //如果非空
- {
- if (value instanceof List<?>) //如果为list
- {
- if(!((List)value).isEmpty() ) //如果list非空
- having.add( new Criterion(conditions,value));
- }
- else //如果为其他直接添加
- having.add( new Criterion(conditions,value));
- }
- }
- //为了适应动态参数而重写的having方法(单个参数或者in的情况),有close关闭符号的情况
- /**
- * 设置having子语句(三个参数的情况)支持单个参数或者in的情况,有close关闭符号的情况 <br/>
- * 切记having里面的字段group by里面必须有,不然会触发sql语法错误异常<br/>
- * @param conditions: 连接条件,没有传动态参数的查询条件部分,必须包含3部分内容:<br/>
- * 连接规则:(and 或者 or)+ 字段列:(field1)+ 运算符 <br/>
- * 运算符:必须以下运算符中的一个( > 或者 >= 或者 < 或者 <= 或者 <br/>
- * = 或者 <> 或者!= 或者 like 或者 not like 或者 in 或者 not in ) <br/>
- * @param value: 参数值,Object对象,支持任何类型<br/>
- * 注意:如果conditions的运算符是in, 则value部分必须传递一个list的对象,<br/>
- * list对象至少要包含一个Object类型的元素;<br/>
- * 如果conditions的运算符是like部分,则value部分可以在"value1"值的左右两边加上%或者_的通配符<br/>
- * %:表示匹配任意个字符;_:表示匹配一个字符<br/>
- * @example conditions参数例子:" and table1.id= " 或者" and table1.id like "
- * @param close: 关闭符号,只有在处理or条件的时候才会用到,其他时候设置null或者""
- */
- public void HAVING(String conditions,Object value,String close)
- {
- if(value!=null) //如果非空
- {
- if (value instanceof List<?>) //如果为list
- {
- if(!((List)value).isEmpty() ) //如果list非空
- having.add( new Criterion(conditions,value,close));
- }
- else //如果为其他直接添加
- having.add( new Criterion(conditions,value,close));
- }
- }
- //为了适应动态参数而重写的having方法(between的情况),有close关闭符号的情况
- /**
- * 设置having子语句(四个参数的情况)支持between的情况,有close关闭符号的情况<br/>
- * 切记having里面的字段group by里面必须有,不然会触发sql语法错误异常<br/>
- * @param conditions: 连接条件,没有传动态参数的查询条件部分,必须包含3部分内容:<br/>
- * 连接规则:(and 或者 or)+ 字段列:(field1)+ 运算符 <br/>
- * 运算符:必须以下运算符中的一个( between 或者 not between )<br/>
- * @param value: 参数值,Object对象,between的参数值左部分,支持任何类型<br/>
- * @param secondValue: 参数值,Object对象,between的参数值右部分,支持任何类型<br/>
- * @example conditions参数例子:" and table1.id= " 或者" and table1.id like "
- * @param close: 关闭符号,只有在处理or条件的时候才会用到,其他时候设置null或者""
- */
- public void HAVING(String conditions,Object value,Object secondValue,String close)
- {
- if(value!=null&&secondValue!=null)
- having.add( new Criterion(conditions,value,secondValue,close));
- }
- /**
- * 设置排序子语句
- * 切记ORDER_BY里面的字段select里面的字段必须有,不然会触发sql语法错误异常
- * @param conditions: 排序条件
- * @example conditions参数例子:"table1.id decs"
- */
- public void ORDER_BY(String conditions)
- {
- orderBy.add(conditions);
- }
-
- private StringBuilder selectClause( String keyword,
- List<String> parts, String open, String close, String conjunction)
- {
- StringBuilder builder=new StringBuilder();
- if (!parts.isEmpty())
- {
- if (builder.length() > 0)
- builder.append("
");
- builder.append(keyword);
- builder.append(" ");
- builder.append(open);
- String last = "________";
- for (int i = 0, n = parts.size(); i < n; i++)
- {
- String part = parts.get(i);
- if (i > 0 && !part.equals(AND) && !part.equals(OR) && !last.equals(AND)
- && !last.equals(OR))
- {
- builder.append(conjunction);
- }
- builder.append(part);
- last = part;
- }
- builder.append(close);
- }
- return builder;
- }
-
- private void whereClause()
- {
- if(where.size()>0)
- {
- System.out.print(" WHERE 1=1 ");
- for(Criterion cri:where)
- {
- if(cri.isNoValue())
- System.out.print(cri.getCondition());
- if(cri.isSingleValue())
- System.out.print(cri.getCondition()+" ""+cri.getValue()+""");
- if(cri.isBetweenValue())
- System.out.print(cri.getCondition()+" ""+cri.getValue()+"" and ""+cri.getSecondValue()+""");
- if(cri.isListValue())
- {
- StringBuilder strb= new StringBuilder();
- strb.append(cri.getCondition());
- strb.append(" (");
- List list=(List)cri.getValue();
- for(int i=0;i<list.size();i++)
- {
- Object o=list.get(i);
- strb.append("""+o+""");
- if(i<list.size()-1)
- strb.append(",");
- }
-