package com.github.walker.easydb.criterion; import com.github.walker.easydb.assistant.MappingUtil; import com.github.walker.easydb.datatype.EString; import java.util.Arrays; import java.util.HashSet; import java.util.Iterator; import java.util.Set; /** * Constrains the property to a specified list of values * * @author HuQingmiao */ public class InExpression extends Criteria { private final String colName; private final Object[] values; protected InExpression(String propertyName, Object[] values) { this.colName = MappingUtil.getColumnName(propertyName); this.values = values; } public String toSqlString() { if (values == null || values.length == 0) { return " 1 = 2 "; } // return colName + " IN (" + toString(values) + ")"; return buildInClause(colName, values); } // private String toString(Object[] array) { // int len = array.length; // if (len == 0) // return ""; // // StringBuffer buf = new StringBuffer(len * 10); // // for (int i = 0; i < len - 1; i++) { // if (array[i] instanceof String || array[i] instanceof EString || array[i] // instanceof Character) { // buf.append("\'").append(array[i]).append("\',"); // } else { // buf.append(array[i]).append(","); // } // } // // if (array[len - 1] instanceof String // || array[len - 1] instanceof EString || array[len - 1] instanceof // Character) { // buf.append("\'").append(array[len - 1]).append("\'"); // } else { // buf.append(array[len - 1]); // } // // return buf.toString(); // } /** * 构造形如" A.COLUMN IN (a,b,c,...)"的IN子句. 若参数set为空, 则返回 "1=1". 若参数 set为NULL, * 将会抛出java.lang.NullPointerException. * * @param colName 列名,或带有表的别名的列名 * @param set 含字符或数字类型元素的集合 * @return 返回形如" A.COLUMN IN (a,b,c,...)"的IN子句; 但若参数array长度为0, 则返回 "1=1" */ @SuppressWarnings({"rawtypes", "unchecked"}) public static String buildInClause(String colName, Set set) { final int maxItemCnt = 1000; // in子句允许的最大项数 if (set.isEmpty()) { return " 1 =1 "; } StringBuffer buff = new StringBuffer(); if (set.size() <= maxItemCnt) { buff.append(colName); buff.append(" IN (" + toString(set) + ") "); } else { // 将集合减裁后分别存放其中对象的子集合 Set[] subSetArray = new HashSet[(set.size() - 1) / maxItemCnt + 1]; // 将子集合初始化 for (int i = 0; i < subSetArray.length; i++) { subSetArray[i] = new HashSet(); } int i = 0;// 从第一个元素开始迭代 for (Iterator it = set.iterator(); it.hasNext(); ) { Object obj = it.next(); // 计算当前对象应该复制到哪个子集合 int idx = i / maxItemCnt; subSetArray[idx].add(obj); i++; } buff.append(" ( "); buff.append(colName); buff.append(" IN (" + toString(subSetArray[0]) + ") "); for (i = 1; i < subSetArray.length; i++) { buff.append(" OR "); buff.append(colName); buff.append(" IN (" + toString(subSetArray[i]) + ") "); } buff.append(" ) "); for (i = 0; i < subSetArray.length; i++) { subSetArray[i].clear(); subSetArray[i] = null; } } return buff.toString(); } /** * 构造形如" A.COLUMN IN (a,b,c,...)"的IN子句. 若参数array长度为0, 则返回 "1=1". * * @param colName 列名,或带有表的别名的列名. * @param array 含字符或数字类型元素的数组 * @return 返回形如" A.COLUMN IN (a,b,c,...)"的IN子句; 但若参数array长度为0, 则返回 "1=1" */ public static String buildInClause(String colName, Object[] array) { HashSet<Object> set = new HashSet<Object>(Arrays.asList(array)); return buildInClause(colName, set); } /** * 将Set<Object>中的项目转换成以逗号分隔的内容. * * @param set Set<String> * @return 类似如:"4,5,33,43,'a' "的字符串 */ private static String toString(Set<Object> set) { StringBuffer buff = new StringBuffer(); for (Iterator<Object> it = set.iterator(); it.hasNext(); ) { Object obj = it.next(); // 如果是字符或字符串型, 则转出时需要在元素两边加上单引号' if (obj instanceof String || obj instanceof EString || obj instanceof Character) { String s = obj.toString(); s = s.replace("\'", "''");// 将条件中的单引号替换成丙个单引号 if (!s.trim().equals("")) { buff.append("\'"); buff.append(s.trim()); buff.append("\',"); } } else { buff.append(obj.toString()); buff.append(","); } } if (buff.length() > 0) { buff.deleteCharAt(buff.length() - 1); } return buff.toString(); } // public static void main(String args[]) { // StringBuffer sql = new StringBuffer(); // // sql.append(" SELECT A.OWNER_CODE,A.CS_CP_NO,A.CS_CP_ID,A.CR_NO,A.BELONG_AREA "); // sql.append(" ,A.CR_NAME,A.CR_MODEL,A.GOODS_CODE "); // sql.append(" ,A.GOODS_NAME,A.GOODS_MODEL,A.DECL_UNIT"); // sql.append(" ,A.FACTORY_WT,A.USED_LJ_WT,A.STATE, A.APPLY_REMARK "); // sql.append(" ,A.HG_AUDIT_CODE,A.HG_AUDIT_NAME,A.HG_AUDIT_TIME "); // sql.append(" ,A.HG_FIRST_AUDIT_CODE,A.HG_FIRST_AUDIT_NAME,A.HG_FIRST_AUDIT_TIME "); // sql.append(" ,A.INNER_RECEIVE_TIME,A.CUSTOM_CODE "); // sql.append(" FROM CONSUME_CP_FINAL A"); // sql.append(" WHERE 1=1 "); // // HashSet<Object> customSet = new HashSet<Object>(); // customSet.add("asd"); // if (customSet != null && !customSet.isEmpty()) { // sql.append(" AND " + InExpression.buildInClause("A.CUSTOM_CODE", customSet)); // } // // System.out.println(sql.toString()); // } }