Welcome 微信登录

首页 / 数据库 / MySQL / MyBatis3下的通用SQL的select语句执行类

项目中为了使项目的数据库操作从dao层转移到service层,只好写一个通用的sql语句拼接类和相应的mapper类和mapper的xml文件,自定义的SelectBuilder.java的代码如下:
  1. import java.io.IOException;  
  2. import java.util.ArrayList;  
  3. import java.util.List;  
  4.   
  5. import com.util.StringHelper;  
  6.   
  7. /** 
  8.  * SelectBuilder:SQL条件拼接类,该类只做sql语句的拼接 
  9.  * @author LMH 修改 
  10.  * @notice    注意:为了用好该类,必须熟悉掌握sql语句完整语法 
  11.  * @SQLGrammar  SELECT语句的完整语法为:  
  12.  *SELECT[ALL|DISTINCT|DISTINCTROW|TOP]  <br/> 
  13.  *{*|talbe.*|[table.]field1[AS alias1][,[table.]field2[AS alias2][,…]]} <br/> 
  14.  *FROM tableexpression[,…][IN externaldatabase] <br/> 
  15.  *[WHERE…] <br/> 
  16.  *[GROUP BY…] <br/> 
  17.  *[HAVING…] <br/> 
  18.  *[ORDER BY…] <br/> 
  19.  *[WITH OWNERACCESS OPTION] <br/> 
  20.  *说明: <br/> 
  21.  *用中括号([])括起来的部分表示是可选的,用大括号({})括起来的部分是表示必须从中选择其中的一个。 <br/> 
  22.  * 
  23.  */  
  24. public class SelectBuilder  
  25. {  
  26.     private static final String AND = ")  AND (";  
  27.   
  28.     private static final String OR = ")  OR (";  
  29.       
  30.     List<String> select = new ArrayList<String>();  
  31.   
  32.     List<String> from = new ArrayList<String>();  
  33.   
  34.     List<String> join = new ArrayList<String>();  
  35.   
  36.     List<String> innerJoin = new ArrayList<String>();  
  37.   
  38.     List<String> outerJoin = new ArrayList<String>();  
  39.   
  40.     List<String> leftOuterJoin = new ArrayList<String>();  
  41.   
  42.     List<String> rightOuterJoin = new ArrayList<String>();  
  43.   
  44.     List<Criterion> where = new ArrayList<Criterion>();  
  45.   
  46.     List<Criterion> having = new ArrayList<Criterion>();  
  47.   
  48.     List<String> groupBy = new ArrayList<String>();  
  49.   
  50.     List<String> orderBy = new ArrayList<String>();  
  51.   
  52.     List<String> lastList = new ArrayList<String>();  
  53.   
  54.     boolean distinct;  
  55.   
  56.     /** 
  57.      * 设置SQL语句中从select到from的部分 
  58.      * @param conditons 查詢的内容,可以写字段,聚合函数等 
  59.      * @example 参数例子:" table1.id as id,table2.mc as mc ", 
  60.      * @notice  注意:如果要查询的字段名有相同的,必须用as **的方式进行区分,不然会不能正确set进hashmap里 
  61.      *  
  62.      */  
  63.     public  void SELECT(String conditons)  
  64.     {  
  65.         select.add(conditons);  
  66.     }  
  67.      /** 
  68.      * 设置SQL语句中从select distinct到from的部分,可以写字段,聚合函数等 
  69.      * @param columns 查詢的字段列表  
  70.      * @example 参数例子:" table1.id as id,table2.mc as mc ", 
  71.      * @notice  注意:如果要查询的字段名有相同的,必须用as **的方式进行区分,不然会不能正确set进hashmap里 
  72.      *  
  73.      */  
  74.     public  void SELECT_DISTINCT(String columns)  
  75.     {  
  76.         distinct = true;  
  77.         SELECT(columns);  
  78.     }  
  79.       
  80.     /** 
  81.      *  设置SQL语句中从from到where的部分 
  82.      * @param table: 表名列表,可以是要查询的表名列表,或者直接加上join连接 
  83.      * @example 参数例子:" table1 " 或者" table1,table2 " 
  84.      */  
  85.     public  void FROM(String table)  
  86.     {  
  87.         from.add(table);  
  88.     }  
  89.     /** 
  90.     * 设置JOIN连接条件 <br/> 
  91.     * 切记用了join相关的链接,则form里只能有一个表,而且,join函数之后,后面不得再加from函数 
  92.     * @param join:JOIN连接条件,由3部分组成:表名 别名 + on +连接条件 
  93.     * @example join参数例子:" bmd_mss b on b.bmd_h=loc.x_h " 
  94.     */  
  95.     public  void JOIN(String join)  
  96.     {  
  97.         this.join.add(join);  
  98.     }  
  99.     /** 
  100.     * 设置INNER_JOIN连接条件 <br/> 
  101.     * 切记用了join相关的链接,则form里只能有一个表,而且,join函数之后,后面不得再加from函数 
  102.     * @param join:INNER_JOIN连接条件,由3部分组成:表名 别名 + on +连接条件 
  103.     * @example join参数例子:" bmd_mss b on b.bmd_h=loc.x_h " 
  104.     */  
  105.     public  void INNER_JOIN(String join)  
  106.     {  
  107.         innerJoin.add(join);  
  108.     }  
  109.      /** 
  110.       * 设置LEFT_OUTER_JOIN连接条件 
  111.      * 用了join相关的链接,则form里只能有一个表,而且,join之后,后面不得再加form函数 
  112.      * @param join:LEFT_OUTER_JOIN连接条件,由3部分组成:表名 别名 + on +连接条件 
  113.      * @example join参数例子:" bmd_mss b on b.bmd_h=loc.x_h " 
  114.      */  
  115.     public  void LEFT_OUTER_JOIN(String join)  
  116.     {  
  117.         leftOuterJoin.add(join);  
  118.     }  
  119.     /** 
  120.     * 设置RIGHT_OUTER_JOIN连接条件 
  121.     * 用了join相关的链接,则form里只能有一个表,而且,join之后,后面不得再加form函数 
  122.     * @param join:RIGHT_OUTER_JOIN连接条件,由3部分组成:表名 别名 + on +连接条件 
  123.     * @example join参数例子:" bmd_mss b on b.bmd_h=loc.x_h " 
  124.     */  
  125.     public  void RIGHT_OUTER_JOIN(String join)  
  126.     {  
  127.         rightOuterJoin.add(join);  
  128.     }  
  129.     /** 
  130.     * 设置OUTER_JOIN连接条件 
  131.     * 用了join相关的链接,则form里只能有一个表,而且,join之后,后面不得再加form函数 
  132.     * @param join:OUTER_JOIN连接条件,由3部分组成:表名 别名 + on +连接条件 
  133.     * @example join参数例子:" bmd_mss b on b.bmd_h=loc.x_h " 
  134.     */  
  135.     public  void OUTER_JOIN(String join)  
  136.     {  
  137.         outerJoin.add(join);  
  138.     }  
  139.   
  140.     //为了适应动态参数而重写的where方法(没有参数的情况)   
  141.     /** 
  142.      *设置where子语句(一个参数的情况) 
  143.      * @param conditions:  连接条件,没有传动态参数的查询条件部分<br/> 
  144.      * 一个静态查询条件必须包含4部分内容:连接规则 字段列 运算符 值 <br/> 
  145.      * 连接规则: (and 或者 or)<br/> 
  146.      * 字段名: (field1)<br/> 
  147.      * 运算符: 必须以下运算符中的一个( > 或者 >= 或者 < 或者 <= 或者 <br/> 
  148.      * = 或者 <> 或者!= 或者 like 或者 not like 或者 in 或者 not in <br/> 
  149.      * 或者 between 或者 not between )     <br/>    
  150.      * 值 : 注意:如果元素符是in,则值部分必须写成 (value1,value2...)的形式。<br/> 
  151.      *             如果元素符是between,则值部分必须为 value1 and value2 的形式,value1为min,value2为max。<br/> 
  152.      *             如果元素符是like,则值部分可以在值的左右两边加上%或者_的通配符。<br/> 
  153.      *                            %:表示匹配任意个字符;_:表示匹配一个字符。<br/> 
  154.      * @example conditions参数例子:" and table1.id=table2.id or table1.mc=table2.mc and table1.id like "%1%" "  
  155.      */  
  156.     public  void WHERE(String conditions)  
  157.     {  
  158.         if(StringHelper.isNotBlank(conditions))  
  159.         where.add( new Criterion(conditions));  
  160.     }  
  161.     //为了适应动态参数而重写的where方法,(单个参数或者in的情况)   
  162.     /** 
  163.      * 设置where子语句(两个参数的情况)支持单个参数或者in的情况 
  164.      * @param conditions:  连接条件,没有传动态参数的查询条件部分,必须包含3部分内容:<br/> 
  165.      *                  连接规则:(and 或者 or)+ 字段列:(field1)+ 运算符 <br/> 
  166.      *                  运算符:必须以下运算符中的一个( > 或者 >= 或者 < 或者 <= 或者 = 或者  <br/> 
  167.      *                 <> 或者!= 或者 like 或者 not like 或者 in 或者not in  )  <br/>       
  168.      * @param value:  参数值,Object对象,支持任何类型<br/> 
  169.      *                 注意:如果conditions的运算符是in, 则value部分可以传递一个list的对象,<br/> 
  170.      *                 list对象至少要包含一个Object类型的元素;如果conditions的运算符是like<br/> 
  171.      *                 部分,则value部分可以在"value1"值的左右两边加上%或者_的通配符。<br/> 
  172.      *                  %:表示匹配任意个字符;_:表示匹配一个字符<br/> 
  173.      * @example conditions参数例子:" and table1.id= " 或者" and table1.id like  " 
  174.      */  
  175.     public void WHERE(String conditions,Object value)  
  176.     {  
  177.         if(value!=null)    //如果非空   
  178.         {  
  179.             if (value instanceof List<?>) //如果为list   
  180.             {  
  181.               if(!((List)value).isEmpty() ) //如果list非空   
  182.                 where.add( new Criterion(conditions,value));  
  183.             }  
  184.             else  //如果为其他直接添加   
  185.             where.add( new Criterion(conditions,value));  
  186.         }  
  187.     }  
  188.     //为了适应动态参数而重写的where方法(单个参数或者in的情况),有close关闭符号的情况   
  189.     /** 
  190.      * 设置where子语句(三个参数的情况)支持单个参数或者in的情况,有close关闭符号的情况 
  191.      * @param conditions:  连接条件,没有传动态参数的查询条件部分,必须包含3部分内容:<br/> 
  192.      *                连接规则:(and 或者 or)+ 字段列:(field1)+ 运算符 <br/> 
  193.      *                运算符:必须以下运算符中的一个( > 或者 >= 或者 < 或者 <= 或者  <br/> 
  194.      *                = 或者 <> 或者!= 或者 like 或者 not like 或者 in 或者 not in  )  <br/>    
  195.      * @param value:  参数值,Object对象,支持任何类型<br/> 
  196.      *               注意:如果conditions的运算符是in, 则value部分可以传递一个list的对象,list对象至少要包含一个Object类型的元素<br/> 
  197.      *               如果conditions的运算符是like部分,则value部分可以在"value1"值的左右两边加上%或者_的通配符<br/> 
  198.      *               %:表示匹配任意个字符;_:表示匹配一个字符<br/> 
  199.      * @example conditions参数例子:" and table1.id= " 或者" and table1.id like  " 
  200.      * @param close: 关闭符号,只有在处理or条件的时候才会用到,其他时候设置null或者"" 
  201.      */  
  202.     public void WHERE(String conditions,Object value,String close)  
  203.     {  
  204.         if(value!=null)    //如果非空   
  205.         {  
  206.             if (value instanceof List<?>) //如果为list   
  207.             {  
  208.               if(!((List)value).isEmpty() ) //如果list非空   
  209.                 where.add( new Criterion(conditions,value,close));  
  210.             }  
  211.             else  //如果为其他直接添加   
  212.             where.add( new Criterion(conditions,value,close));  
  213.         }  
  214.     }  
  215.     //为了适应动态参数而重写的where方法(between的情况),有close关闭符号的情况   
  216.     /** 
  217.      * 设置where子语句(四个参数的情况)支持between的情况,有close关闭符号的情况 
  218.      * @param conditions:  连接条件,没有传动态参数的查询条件部分,必须包含3部分内容:<br/> 
  219.      *                连接规则:(and 或者 or)+ 字段列:(field1)+ 运算符 <br/> 
  220.      *                运算符:必须以下运算符中的一个(  between 或者 not between )<br/>   
  221.      * @param value:  参数值,Object对象,between的参数值左部分,支持任何类型<br/>   
  222.      * @param secondValue    参数值,Object对象,between的参数值右部分,支持任何类型<br/>   
  223.      * @example conditions参数例子:" and table1.id= " 或者" and table1.id like  " 
  224.      * @param close: 关闭符号,只有在处理or条件的时候才会用到,其他时候设置null或者"" 
  225.      */  
  226.     public  void WHERE(String conditions,Object value,Object secondValue,String close)  
  227.     {  
  228.         if(value!=null&&secondValue!=null)  
  229.         where.add( new Criterion(conditions,value,secondValue,close));  
  230.     }  
  231.   
  232.     /** 
  233.      * 设置分组字段列表 
  234.      * 切记GROUP_BY里面的字段select里面的字段必须有,不然会触发sql语法错误异常 
  235.      * @param columns: 分组字段 
  236.      * @example columns参数例子:"table1.id,table2.mc " 
  237.      */  
  238.     public  void GROUP_BY(String columns)  
  239.     {  
  240.         groupBy.add(columns);  
  241.     }  
  242.   
  243.   
  244.     //为了适应动态参数而重写的having方法(没有参数的情况)   
  245.     /** 
  246.      *  
  247.      * 设置having子语句(一个参数的情况)<br/> 
  248.      * 切记having里面的字段group by里面必须有,不然会触发sql语法错误异常<br/> 
  249.      * @param conditions:  连接条件,没有传动态参数的查询条件部分<br/> 
  250.      * 一个静态查询条件必须包含4部分内容:连接规则 字段列 运算符 值 <br/> 
  251.      * 连接规则: (and 或者 or)<br/> 
  252.      * 字段名: (field1)<br/> 
  253.      * 运算符: 必须以下运算符中的一个( > 或者 >= 或者 < 或者 <= 或者 <br/> 
  254.      * = 或者 <> 或者!= 或者 like 或者 not like 或者 in 或者 not in <br/> 
  255.      * 或者 between 或者 not between )     <br/>    
  256.      * 值: 注意:如果元素符是in,则值部分必须写成 (value1,value2...)的形式。<br/> 
  257.      *             如果元素符是between,则值部分必须为 value1 and value2 的形式,value1为min,value2为max。<br/> 
  258.      *             如果元素符是like,则值部分可以在值的左右两边加上%或者_的通配符。<br/> 
  259.      *                            %:表示匹配任意个字符;_:表示匹配一个字符。<br/> 
  260.      * @example conditions参数例子:" and table1.id=table2.id or table1.mc=table2.mc and table1.id like "%1%" "  
  261.      */  
  262.     public  void HAVING(String conditions)  
  263.     {  
  264.         if(StringHelper.isNotBlank(conditions))  
  265.         having.add( new Criterion(conditions));  
  266.     }  
  267.     //为了适应动态参数而重写的having方法(单个参数或者in的情况)   
  268.     /** 
  269.      * 设置having子语句(两个参数的情况)支持单个参数或者in的情况<br/> 
  270.      * 切记having里面的字段group by里面必须有,不然会触发sql语法错误异常<br/> 
  271.      * @param conditions:  连接条件,没有传动态参数的查询条件部分,必须包含3部分内容:<br/> 
  272.      *                  连接规则:(and 或者 or)+ 字段列:(field1)+ 运算符 <br/> 
  273.      *                  运算符:必须以下运算符中的一个( > 或者 >= 或者 < 或者 <= 或者 = 或者  <br/> 
  274.      *                 <> 或者!= 或者 like 或者 not like 或者 in 或者not in  )  <br/>       
  275.      * @param value:  参数值,Object对象,支持任何类型<br/> 
  276.      *                 注意:如果conditions的运算符是in, 则value部分可以传递一个list的对象,<br/> 
  277.      *                 list对象至少要包含一个Object类型的元素;如果conditions的运算符是like<br/> 
  278.      *                 部分,则value部分可以在"value1"值的左右两边加上%或者_的通配符。<br/> 
  279.      *                  %:表示匹配任意个字符;_:表示匹配一个字符<br/> 
  280.      * @example conditions参数例子:" and table1.id= " 或者" and table1.id like  " 
  281.      */  
  282.     public  void HAVING(String conditions,Object value)  
  283.     {  
  284.         if(value!=null)    //如果非空   
  285.         {  
  286.             if (value instanceof List<?>) //如果为list   
  287.             {  
  288.               if(!((List)value).isEmpty() ) //如果list非空   
  289.               having.add( new Criterion(conditions,value));  
  290.             }  
  291.             else  //如果为其他直接添加   
  292.             having.add( new Criterion(conditions,value));  
  293.         }  
  294.     }  
  295.     //为了适应动态参数而重写的having方法(单个参数或者in的情况),有close关闭符号的情况   
  296.     /** 
  297.      * 设置having子语句(三个参数的情况)支持单个参数或者in的情况,有close关闭符号的情况 <br/> 
  298.      * 切记having里面的字段group by里面必须有,不然会触发sql语法错误异常<br/> 
  299.      * @param conditions:  连接条件,没有传动态参数的查询条件部分,必须包含3部分内容:<br/> 
  300.      *                连接规则:(and 或者 or)+ 字段列:(field1)+ 运算符 <br/> 
  301.      *                运算符:必须以下运算符中的一个( > 或者 >= 或者 < 或者 <= 或者  <br/> 
  302.      *                = 或者 <> 或者!= 或者 like 或者 not like 或者 in 或者 not in  )  <br/>    
  303.      * @param value:  参数值,Object对象,支持任何类型<br/> 
  304.      *               注意:如果conditions的运算符是in, 则value部分必须传递一个list的对象,<br/> 
  305.      *               list对象至少要包含一个Object类型的元素;<br/> 
  306.      *               如果conditions的运算符是like部分,则value部分可以在"value1"值的左右两边加上%或者_的通配符<br/> 
  307.      *               %:表示匹配任意个字符;_:表示匹配一个字符<br/> 
  308.      * @example conditions参数例子:" and table1.id= " 或者" and table1.id like  " 
  309.      * @param close: 关闭符号,只有在处理or条件的时候才会用到,其他时候设置null或者"" 
  310.      */  
  311.     public  void HAVING(String conditions,Object value,String close)  
  312.     {  
  313.         if(value!=null)    //如果非空   
  314.         {  
  315.             if (value instanceof List<?>) //如果为list   
  316.             {  
  317.               if(!((List)value).isEmpty() ) //如果list非空   
  318.               having.add( new Criterion(conditions,value,close));  
  319.             }  
  320.             else  //如果为其他直接添加   
  321.             having.add( new Criterion(conditions,value,close));  
  322.         }  
  323.     }  
  324.     //为了适应动态参数而重写的having方法(between的情况),有close关闭符号的情况   
  325.     /** 
  326.      * 设置having子语句(四个参数的情况)支持between的情况,有close关闭符号的情况<br/> 
  327.      * 切记having里面的字段group by里面必须有,不然会触发sql语法错误异常<br/> 
  328.      * @param conditions:  连接条件,没有传动态参数的查询条件部分,必须包含3部分内容:<br/> 
  329.      *                连接规则:(and 或者 or)+ 字段列:(field1)+ 运算符 <br/> 
  330.      *                运算符:必须以下运算符中的一个(  between 或者 not between )<br/>   
  331.      * @param value:  参数值,Object对象,between的参数值左部分,支持任何类型<br/>   
  332.      * @param secondValue: 参数值,Object对象,between的参数值右部分,支持任何类型<br/>   
  333.      * @example conditions参数例子:" and table1.id= " 或者" and table1.id like  " 
  334.      * @param close: 关闭符号,只有在处理or条件的时候才会用到,其他时候设置null或者"" 
  335.      */  
  336.     public  void HAVING(String conditions,Object value,Object secondValue,String close)  
  337.     {  
  338.         if(value!=null&&secondValue!=null)  
  339.         having.add( new Criterion(conditions,value,secondValue,close));  
  340.     }  
  341.     /** 
  342.      * 设置排序子语句 
  343.      * 切记ORDER_BY里面的字段select里面的字段必须有,不然会触发sql语法错误异常 
  344.      * @param conditions: 排序条件 
  345.      * @example conditions参数例子:"table1.id decs" 
  346.      */  
  347.     public  void ORDER_BY(String conditions)  
  348.     {  
  349.         orderBy.add(conditions);  
  350.     }  
  351.   
  352.     private  StringBuilder selectClause( String keyword,  
  353.             List<String> parts, String open, String close, String conjunction)  
  354.     {  
  355.         StringBuilder builder=new StringBuilder();  
  356.         if (!parts.isEmpty())  
  357.         {  
  358.             if (builder.length() > 0)  
  359.                 builder.append(" ");  
  360.             builder.append(keyword);  
  361.             builder.append(" ");  
  362.             builder.append(open);  
  363.             String last = "________";  
  364.             for (int i = 0, n = parts.size(); i < n; i++)  
  365.             {  
  366.                 String part = parts.get(i);  
  367.                 if (i > 0 && !part.equals(AND) && !part.equals(OR) && !last.equals(AND)  
  368.                         && !last.equals(OR))  
  369.                 {  
  370.                     builder.append(conjunction);  
  371.                 }  
  372.                 builder.append(part);  
  373.                 last = part;  
  374.             }  
  375.             builder.append(close);  
  376.         }  
  377.         return builder;  
  378.     }  
  379.       
  380.     private  void whereClause()  
  381.     {  
  382.         if(where.size()>0)  
  383.         {  
  384.             System.out.print(" WHERE 1=1 ");      
  385.             for(Criterion cri:where)  
  386.             {  
  387.                 if(cri.isNoValue())  
  388.                 System.out.print(cri.getCondition());  
  389.                 if(cri.isSingleValue())  
  390.                  System.out.print(cri.getCondition()+" ""+cri.getValue()+""");  
  391.                 if(cri.isBetweenValue())  
  392.                   System.out.print(cri.getCondition()+" ""+cri.getValue()+"" and ""+cri.getSecondValue()+""");  
  393.                 if(cri.isListValue())  
  394.                 {   
  395.                     StringBuilder strb= new StringBuilder();  
  396.                     strb.append(cri.getCondition());  
  397.                     strb.append(" (");  
  398.                     List list=(List)cri.getValue();  
  399.                     forint i=0;i<list.size();i++)  
  400.                     {  
  401.                         Object o=list.get(i);  
  402.                         strb.append("""+o+""");  
  403.                         if(i<list.size()-1)  
  404.                          strb.append(",");                    
  405.                     }  
  406.