package org.hsweb.web.mybatis.builder; import org.apache.commons.beanutils.BeanUtilsBean; import org.apache.commons.beanutils.PropertyUtilsBean; import org.apache.ibatis.mapping.ResultMap; import org.apache.ibatis.mapping.ResultMapping; import org.hsweb.commons.DateTimeUtils; import org.hsweb.commons.StringUtils; import org.hsweb.ezorm.core.param.Param; import org.hsweb.ezorm.core.param.Sort; import org.hsweb.ezorm.core.param.Term; import org.hsweb.ezorm.rdb.meta.RDBColumnMetaData; import org.hsweb.ezorm.rdb.render.dialect.Dialect; import org.hsweb.web.bean.common.InsertParam; import org.hsweb.web.bean.common.QueryParam; import org.hsweb.web.bean.common.UpdateParam; import org.hsweb.web.mybatis.utils.ResultMapsUtils; import org.hsweb.web.mybatis.utils.SqlAppender; import java.sql.JDBCType; import java.sql.SQLException; import java.util.*; @Deprecated public class DefaultSqlParamBuilder { public Dialect getDialect() { return Dialect.ORACLE; } public boolean filedToUpperCase() { return true; } protected static final Map<Class, String> simpleName = new HashMap<>(); private static DefaultSqlParamBuilder instance = new DefaultSqlParamBuilder(); protected PropertyUtilsBean propertyUtils = BeanUtilsBean.getInstance().getPropertyUtils(); public DefaultSqlParamBuilder() { simpleName.put(Integer.class, "int"); simpleName.put(Byte.class, "byte"); simpleName.put(Double.class, "double"); simpleName.put(Float.class, "float"); simpleName.put(Boolean.class, "boolean"); simpleName.put(Long.class, "long"); simpleName.put(Short.class, "short"); simpleName.put(Character.class, "char"); simpleName.put(String.class, "string"); simpleName.put(int.class, "int"); simpleName.put(double.class, "double"); simpleName.put(float.class, "float"); simpleName.put(boolean.class, "boolean"); simpleName.put(long.class, "long"); simpleName.put(short.class, "short"); simpleName.put(char.class, "char"); simpleName.put(byte.class, "byte"); } public static DefaultSqlParamBuilder instance() { return instance; } public String encodeFiled(String field) { if (field.contains(".")) { String[] tmp = field.split("[.]"); return tmp[0] + "." + getDialect().getQuoteStart() + (filedToUpperCase() ? (tmp[1].toUpperCase()) : tmp[1]) + getDialect().getQuoteEnd(); } else { return getDialect().getQuoteStart() + (filedToUpperCase() ? (field.toUpperCase()) : field) + getDialect().getQuoteEnd(); } } public KeyWordMapper getKeyWordMapper(String type) { return (paramKey, tableName, term, jdbcType) -> { String termField = term.getColumn(); if (termField.contains(".")) { String[] tmp = termField.split("[.]"); tableName = tmp[0]; termField = tmp[1]; } RDBColumnMetaData field = new RDBColumnMetaData(); field.setName(termField); field.setJdbcType(jdbcType); return getDialect().buildCondition(paramKey, term, field, tableName).toString(); }; } protected Map<String, Object> createConfig(String resultMapId) { ResultMap resultMaps = ResultMapsUtils.getResultMap(resultMapId); Map<String, Object> fieldConfig = new HashMap<>(); List<ResultMapping> resultMappings = new ArrayList<>(resultMaps.getResultMappings()); resultMappings.addAll(resultMaps.getIdResultMappings()); resultMappings.forEach(resultMapping -> { if (resultMapping.getNestedQueryId() == null) { Map<String, Object> config = new HashMap<>(); config.put("jdbcType", resultMapping.getJdbcType()); config.put("javaType", getJavaType(resultMapping.getJavaType())); config.put("property", resultMapping.getProperty()); fieldConfig.put(resultMapping.getColumn(), config); } }); return fieldConfig; } public String buildWhere(String resultMapId, String tableName, List<Term> terms) { Map<String, Object> fieldConfig = createConfig(resultMapId); SqlAppender sqlAppender = new SqlAppender(); buildWhere(fieldConfig, "", tableName, terms, sqlAppender); if (sqlAppender.size() > 0) sqlAppender.removeFirst(); return sqlAppender.toString(); } public String buildInsertSql(String resultMapId, InsertParam param) { ResultMap resultMaps = ResultMapsUtils.getResultMap(resultMapId); Map<String, ResultMapping> mappings = new HashMap<>(); resultMaps.getResultMappings().forEach(resultMapping -> { if (resultMapping.getNestedQueryId() == null && !resultMapping.getProperty().contains(".")) { mappings.put(resultMapping.getColumn(), resultMapping); } }); Object data = param.getData(); List<Object> listData; if (data instanceof Collection) { listData = new ArrayList<>(((Collection) data)); } else { listData = Arrays.asList(param.getData()); } param.setData(listData); String fields = mappings.keySet().stream() .map(str -> new SqlAppender().add(encodeFiled(str), "").toString()) .reduce((f1, f2) -> new SqlAppender().add(f1, ",", f2) .toString()).get(); //批量 int size = listData.size(); SqlAppender batchSql = new SqlAppender(); batchSql.add("(", fields, ")values"); for (int i = 0; i < size; i++) { int index = i; if (i > 0) { batchSql.add(","); } String values = mappings.keySet().stream().map((f1) -> { SqlAppender appender = new SqlAppender(); ResultMapping mapping = mappings.get(f1); appender.add("#{data[" + index + "].", mapping.getProperty(), ",javaType=", getJavaType(mapping.getJavaType()), ",jdbcType=", mapping.getJdbcType(), "}"); return appender.toString(); }).reduce((s1, s2) -> s1 + "," + s2).get(); batchSql.add("(", values, ")"); } return batchSql.toString(); } protected String getJavaType(Class type) { String javaType = simpleName.get(type); if (javaType == null) javaType = type.getName(); return javaType; } public String buildSelectFields(String resultMapId, String tableName, Param param) { Map<String, Object> fieldConfig = createConfig(resultMapId); if (param == null) return "*"; Map<String, String> propertyMapper = getPropertyMapper(fieldConfig, param); SqlAppender appender = new SqlAppender(); propertyMapper.forEach((k, v) -> { if (!appender.isEmpty()) appender.add(","); if (!k.contains(".") || k.split("[.]")[0].equals(tableName)) { appender.add(tableName, ".", encodeFiled(k), " as "); } else { appender.add(encodeFiled(k), " as "); } appender.addEdSpc(getDialect().getQuoteStart(), k, getDialect().getQuoteEnd()); }); if (appender.isEmpty()) return "*"; return appender.toString(); } public String buildUpdateFields(String resultMapId, UpdateParam param) throws Exception { Map<String, Object> fieldConfig = createConfig(resultMapId); param.excludes("id"); Map<String, String> propertyMapper = getPropertyMapper(fieldConfig, param); SqlAppender appender = new SqlAppender(); propertyMapper.forEach((k, v) -> { try { if (v.contains(".")) return; Object obj = propertyUtils.getProperty(param.getData(), v); if (obj != null) { if (!appender.isEmpty()) appender.add(","); Map<String, Object> config = ((Map) fieldConfig.get(k)); appender.add(encodeFiled(k), "=", "#{data.", v); if (config != null) { Object jdbcType = config.get("jdbcType"), javaType = config.get("javaType"); if (jdbcType != null) { appender.add(",jdbcType=", jdbcType); } if (javaType != null) { appender.add(",javaType=", javaType); } } appender.add("}"); } } catch (Exception e) { } }); if (appender.isEmpty()) throw new SQLException("未指定列"); return appender.toString(); } public String buildOrder(String resultMapId, String tableName, QueryParam param) throws Exception { Map<String, Object> fieldConfig = createConfig(resultMapId); QueryParam tmp = new QueryParam(); tmp.setSorts(param.getSorts()); Map<String, String> propertyMapper = getPropertyMapper(fieldConfig, tmp); if (tmp.getSorts().isEmpty()) return ""; Set<Sort> sorts = new LinkedHashSet<>(); param.getSorts().forEach(sort -> { String fieldName = sort.getName(); if (StringUtils.isNullOrEmpty(fieldName)) return; if (fieldName.contains(".")) fieldName = fieldName.split("[.]")[1]; if (propertyMapper.containsKey(fieldName) || propertyMapper.containsValue(fieldName)) { if (propertyMapper.get(fieldName) == null) { for (Map.Entry<String, String> entry : propertyMapper.entrySet()) { if (entry.getValue().equals(fieldName)) { sort.setName(entry.getKey()); } } } sorts.add(sort); } }); if (sorts.isEmpty()) return ""; String sql = sorts.stream() .map(sort -> { String fieldName = sort.getName(); if (fieldName.contains(".")) fieldName = fieldName.split("[.]")[1]; return new SqlAppender() .add(tableName, ".", fieldName, " ", sort.getOrder()).toString(); }) .reduce((s, s1) -> new SqlAppender().add(s, ",", s1).toString()).get(); return " order by ".concat(sql); } public Map<String, String> getPropertyMapper(Map<String, Object> fieldConfig, Param param) { Set<String> includes = param.getIncludes(), excludes = param.getExcludes(); boolean includesIsEmpty = includes.isEmpty(), excludesIsEmpty = excludes.isEmpty(); Map<String, String> propertyMapper = new HashMap<>(); fieldConfig.forEach((k, v) -> { Map<String, Object> config = ((Map) v); String fieldName = (String) config.get("property"); if (fieldName == null) fieldName = k; if (includesIsEmpty && excludesIsEmpty) { propertyMapper.put(k, fieldName); return; } if (excludes.contains(fieldName) || excludes.contains(k)) { return; } if (includesIsEmpty) { propertyMapper.put(k, fieldName); } else if (includes.contains(fieldName) || includes.contains(k)) { propertyMapper.put(k, fieldName); } }); return propertyMapper; } public JDBCType getFieldJDBCType(String field, Map<String, Object> fieldConfig) { if (field == null) return JDBCType.NULL; Object conf = fieldConfig.get(field); if (conf instanceof Map) { try { return JDBCType.valueOf(String.valueOf(((Map) conf).get("jdbcType"))); } catch (Exception e) { } } return JDBCType.VARCHAR; } public String getColumn(Map<String, Object> fieldConfig, String name) { if (name == null) return null; Map<String, Object> config = ((Map) fieldConfig.get(name)); if (config == null) { for (Map.Entry<String, Object> entry : fieldConfig.entrySet()) { String fieldName = (String) ((Map) entry.getValue()).get("property"); if (name.equals(fieldName)) { return entry.getKey(); } } } return name; } public void buildWhere(Map<String, Object> fieldConfig, String prefix, String tableName, List<Term> terms, SqlAppender appender) { if (terms == null || terms.isEmpty()) return; int index = 0; String prefixTmp = StringUtils.concat(prefix, StringUtils.isNullOrEmpty(prefix) ? "" : "."); for (Term term : terms) { String column = getColumn(fieldConfig, term.getColumn()); if (column != null) term.setColumn(column); boolean nullTerm = StringUtils.isNullOrEmpty(term.getColumn()); //不是空条件 也不是可选字段 if (!nullTerm && !fieldConfig.containsKey(term.getColumn())) continue; //不是空条件,值为空 if (!nullTerm && StringUtils.isNullOrEmpty(term.getValue())) continue; //是空条件,但是无嵌套 if (nullTerm && term.getTerms().isEmpty()) continue; //用于sql预编译的参数名 prefix = StringUtils.concat(prefixTmp, "terms[", index++, "]"); //JDBC类型 JDBCType jdbcType = getFieldJDBCType(term.getColumn(), fieldConfig); //转换参数的值 term.setValue(transformationValue(jdbcType, term.getValue())); //添加类型,and 或者 or appender.add(StringUtils.concat(" ", term.getType().toString(), " ")); if (!term.getTerms().isEmpty()) { //构建嵌套的条件 SqlAppender nest = new SqlAppender(); buildWhere(fieldConfig, prefix, tableName, term.getTerms(), nest); //如果嵌套结果为空 if (nest.isEmpty()) { appender.removeLast();//删除最后一个(and 或者 or) continue; } if (nullTerm) { //删除 第一个(and 或者 or) nest.removeFirst(); } appender.add("("); if (!nullTerm) appender.add(getKeyWordMapper(term.getTermType()).fieldMapper(prefix, tableName, term, jdbcType)); appender.addAll(nest); appender.add(")"); } else { if (!nullTerm) appender.add(getKeyWordMapper(term.getTermType()).fieldMapper(prefix, tableName, term, jdbcType)); } } } protected Object transformationValue(JDBCType type, Object value) { switch (type) { case INTEGER: case NUMERIC: if (StringUtils.isInt(type)) return StringUtils.toInt(value); if (StringUtils.isDouble(type)) return StringUtils.toDouble(value); break; case TIMESTAMP: case TIME: case DATE: if (!(value instanceof Date)) { String strValue = String.valueOf(value); Date date = DateTimeUtils.formatUnknownString2Date(strValue); if (date != null) return date; } break; } return value; } public interface KeyWordMapper { String fieldMapper(String paramKey, String tableName, Term term, JDBCType jdbcType); } }