zuy 1 год назад
Родитель
Сommit
1ef1804b3e

+ 1 - 1
car-wash-jdbc/src/main/java/com/kym/DbUtil.java

@@ -250,7 +250,7 @@ public class DbUtil {
      */
     public static boolean isEmptyOrNull(String value) {
 
-        return null == value || value.length() == 0;
+        return null == value || value.isEmpty();
     }
 
     public static boolean isEmptyOrNull(Object value) {

+ 4 - 2
car-wash-jdbc/src/main/java/com/kym/jdbc/BasicQuery.java

@@ -8,10 +8,10 @@ public class BasicQuery {
     public static final int SORT_ASC = 1;
     public static final int SORT_DESC = 2;
 
-    public Long companyId;
+    public Long orgId;
 
     @QF(ignore = true)
-    public int pageNum = 1;
+    public int pageIndex = 1;
 
     @QF(ignore = true)
     public int pageSize = 20;
@@ -23,6 +23,8 @@ public class BasicQuery {
 
     public String[] excludeFields;
 
+    public boolean skipHook; //跳过钩子
+
 
     public BasicQuery() {
 

+ 3 - 3
car-wash-jdbc/src/main/java/com/kym/jdbc/Bean.java

@@ -16,7 +16,7 @@ public class Bean<T> implements Serializable {
     @Serial
     private static final long serialVersionUID = 1L;
     public long count;
-    public int pageNum;
+    public int pageIndex;
     public int pageSize;
     public List<T> list;
 
@@ -28,8 +28,8 @@ public class Bean<T> implements Serializable {
         this.count = list.size();
     }
 
-    public Bean(List<T> list, long count, int pageNum, int pageSize) {
-        this.pageNum = pageNum;
+    public Bean(List<T> list, long count, int pageIndex, int pageSize) {
+        this.pageIndex = pageIndex;
         this.pageSize = pageSize;
         this.list = list;
         this.count = count;

+ 2 - 2
car-wash-jdbc/src/main/java/com/kym/jdbc/OBuilder.java

@@ -142,8 +142,8 @@ public class OBuilder extends IBuilder {
                         } else if ("pageSize".equals(fieldName)) {
                             int pageSize = (int) val;
                             if (pageSize > 0) {
-                                int pageNum = (int) DbUtil.getFieldValue(query, "pageNum");
-                                builder.limit(Math.max(0, (pageNum - 1) * pageSize), pageSize);
+                                int pageIndex = (int) DbUtil.getFieldValue(query, "pageIndex");
+                                builder.limit(Math.max(0, (pageIndex - 1) * pageSize), pageSize);
                             }
                         }
                     }

+ 9 - 0
car-wash-jdbc/src/main/java/com/kym/jdbc/SQLEntity.java

@@ -13,4 +13,13 @@ public class SQLEntity {
     public String sql;
     public Object[] parameters;
 
+    public SQLEntity() {
+
+    }
+
+    public SQLEntity(String sql, Object[] parameters) {
+        this.sql = sql;
+        this.parameters = parameters;
+    }
+
 }

+ 16 - 14
car-wash-jdbc/src/main/java/com/kym/jdbc/express/DeleteSQLExpress.java

@@ -20,16 +20,15 @@ public class DeleteSQLExpress implements SQLExpress<SQLEntity> {
     private final Logger logger = LoggerFactory.getLogger(DeleteSQLExpress.class);
 
     /**
-     * insert 的表名
+     * delete  的表名
      */
     private String table;
 
     /**
-     * insert的字段名
+     * delete 的条件
      */
     private List<Where> conditions = new ArrayList<>();
 
-
     @Override
     public SQLEntity toSQL() {
         if (strict && DbUtil.isEmptyOrNull(this.conditions)) {
@@ -40,21 +39,24 @@ public class DeleteSQLExpress implements SQLExpress<SQLEntity> {
         List<Object> params = new ArrayList<>();
         StringBuilder sbr = new StringBuilder("DELETE FROM ").append(table);
         if (!DbUtil.isEmptyOrNull(conditions)) {
-            sbr.append(" WHERE ");
+            sbr.append(" WHERE 1=1 ");
             conditions.forEach(where -> {
-                if(!DbUtil.isEmptyOrNull(where.key)){
-                    sbr.append(getComma()).append(where.key).append(getComma()).append(" ").append(where.op).append(" ");
+                if (!DbUtil.isEmptyOrNull(where.key)) {
+                    sbr.append(" AND ( ").append(getComma()).append(where.key).append(getComma()).append(" ").append(where.op);
                     if (where.op.contains("in") || where.op.contains("not in")) {
-                        sbr.append(" (?) AND ");
+                        sbr.append(" (?)  ) ");
                     } else {
-                        sbr.append(" ? AND ");
+                        sbr.append(" ? ) ");
                     }
                     params.add(where.value);
-                    //拼接SQL
-                }else{
-//TODO
+                } else {
+                    if (!DbUtil.isEmptyOrNull(where.sql)) {
+                        sbr.append(" (").append(where.sql).append(" ) ");
+                        if (!DbUtil.isEmptyOrNull(where.sqlValues)) {
+                            params.addAll(where.sqlValues);
+                        }
+                    }
                 }
-
             });
         }
         entity.sql = sbr.toString();
@@ -72,8 +74,8 @@ public class DeleteSQLExpress implements SQLExpress<SQLEntity> {
 
 
     public SQLEntity delete(Class<?> clz, OBuilder OBuilder) {
-         table = getTableName(clz, clz.getSimpleName());
-         conditions  = OBuilder.getWheres();
+        table = getTableName(clz, clz.getSimpleName());
+        conditions = OBuilder.getWheres();
         return toSQL();
     }
 

+ 64 - 11
car-wash-jdbc/src/main/java/com/kym/jdbc/express/InsertSQLExpress.java

@@ -9,8 +9,10 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
 import java.lang.reflect.Type;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Date;
 import java.util.List;
 import java.util.Set;
@@ -32,24 +34,25 @@ public class InsertSQLExpress implements SQLExpress<SQLEntity> {
     /**
      * insert的字段名
      */
-    private final List<String> columns = new ArrayList<>();
+    private final List<String> cols = new ArrayList<>();
 
     /**
      * insert的值
      */
     private final List<Object> values = new ArrayList<>();
 
+
     @Override
     public SQLEntity toSQL() {
-        if (DbUtil.isEmptyOrNull(this.columns)) {
-            logger.error("columns is null");
-            throw new DbException("insert parse error because columns is null");
+        if (DbUtil.isEmptyOrNull(this.cols)) {
+            logger.error("cols is null");
+            throw new DbException("insert parse error because cols is null");
         }
         SQLEntity entity = new SQLEntity();
         StringBuilder sbr = new StringBuilder("INSERT INTO ").append(table).append(" (");
-        String collect = columns.stream().map(k -> getComma() + k + getComma()).collect(Collectors.joining(","));
+        String collect = cols.stream().map(k -> getComma() + DbUtil.getColumnName(k) + getComma()).collect(Collectors.joining(","));
         sbr.append(collect).append(") VALUES (");
-        String collect1 = columns.stream().map(k -> "?").collect(Collectors.joining(","));
+        String collect1 = cols.stream().map(k -> "?").collect(Collectors.joining(","));
         sbr.append(collect1).append(")");
         entity.sql = sbr.toString();
         entity.parameters = values.toArray();
@@ -78,14 +81,14 @@ public class InsertSQLExpress implements SQLExpress<SQLEntity> {
      * @param ignoreNull 忽略空字段
      * @param withAutoIncreamentKey 对象是否已赋值自增主键
      * @param exclude 忽略字段
-     * @return
+     * @return SQLEntity sql构造实体
      */
     private SQLEntity insertWithCheck(Object o, boolean ignoreNull, boolean withAutoIncreamentKey, List<String> exclude) {
         table = getTableName(o.getClass(), o.getClass().getSimpleName());
 
         //自带主键
         if (withAutoIncreamentKey) {
-            columns.add("id");
+            cols.add("id");
             try {
                 values.add(DbUtil.getFieldValue(o, DbUtil.getField(o, "id")));
             } catch (NoSuchFieldException e) {
@@ -93,6 +96,9 @@ public class InsertSQLExpress implements SQLExpress<SQLEntity> {
                 throw new IllegalStateException("no primary key value exist.");
             }
         }
+        if(DbUtil.isEmptyOrNull(exclude)){
+            exclude = new ArrayList<>();
+        }
         exclude.add("id");
         Set<Field> fields = DbUtil.getEntityFields(o.getClass());
         for (Field field : fields) {
@@ -112,14 +118,14 @@ public class InsertSQLExpress implements SQLExpress<SQLEntity> {
                         if (null != value) {
                             //TODO 校验值
                             checkFieldValue(field, value, true);
-                            columns.add(fieldName);
+                            cols.add(fieldName);
                             values.add(value);
                         }
                     } else {
                         if (type == Date.class && null == value) {
                             continue;
                         }
-                        columns.add(fieldName);
+                        cols.add(fieldName);
                         values.add(value);
                     }
                 }
@@ -128,6 +134,53 @@ public class InsertSQLExpress implements SQLExpress<SQLEntity> {
         return toSQL();
     }
 
-    //endregion insert
 
+    public final SQLEntity insertBatch(List<?> dtoList) {
+        if (DbUtil.isEmptyOrNull(dtoList)) {
+            throw new IllegalArgumentException("insertBatch no dtoList exists!!!");
+        }
+        List<String> ignores = Arrays.asList("id".split(","));
+        Set<Field> fields = DbUtil.getEntityFields(dtoList.get(0).getClass());
+        List<String> fieldList = new ArrayList<>();
+        for (Field field : fields) {
+            int modifier = field.getModifiers();
+            if (!Modifier.isFinal(modifier) && !Modifier.isStatic(modifier) && field.isAnnotationPresent(DBF.class)) {
+                String fieldName = field.getName();
+                if (!ignores.contains(fieldName)) {
+                    fieldList.add(field.getName());
+                }
+            }
+        }
+
+        return insertBatch(fieldList, dtoList);
+    }
+
+    /**
+     * 无需自己组装SQL
+     */
+    public final SQLEntity insertBatch(List<String> fields, List<?> dtoList) {
+        if (DbUtil.isEmptyOrNull(fields)) {
+            throw new IllegalArgumentException("ERROR# insert fields is empty!");
+        }
+        if (DbUtil.isEmptyOrNull(dtoList)) {
+            throw new IllegalArgumentException("ERROR# insert values is empty!");
+        }
+
+        this.table = getTableName(dtoList.get(0).getClass().getSimpleName());
+        fields.forEach(field -> this.cols.add(DbUtil.getColumnName(field)));
+
+        int fieldSize = fields.size();
+        for (Object o : dtoList) {
+            Object[] ll = new Object[fieldSize];
+            for (int j = 0; j < fieldSize; j++) {
+                ll[j] = DbUtil.getFieldValue(o, fields.get(j));
+            }
+            values.add(ll);
+        }
+
+        return toSQL();
+    }
+
+
+    //endregion
 }

+ 128 - 1
car-wash-jdbc/src/main/java/com/kym/jdbc/express/SQLExpress.java

@@ -1,10 +1,17 @@
 package com.kym.jdbc.express;
 
 import com.kym.DbUtil;
+import com.kym.jdbc.BasicQuery;
 import com.kym.jdbc.OBuilder;
 import com.kym.jdbc.annotations.DBF;
 import com.kym.jdbc.annotations.Entity;
+import com.kym.jdbc.annotations.FK;
+import com.kym.jdbc.annotations.One;
+import com.kym.jdbc.annotations.QE;
+import com.kym.jdbc.annotations.QF;
 import com.kym.jdbc.template.JdbcHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.lang.reflect.Array;
 import java.lang.reflect.Field;
@@ -18,21 +25,134 @@ import java.util.List;
 /**
  * sql表达式构造
  * <p>
- *     mysql\oracle\postgresql\sqlserver\db2\h2\sqlite\人大金仓\达梦\
+ * mysql\oracle\postgresql\sqlserver\db2\h2\sqlite\人大金仓\达梦\
  * </p>
  */
 public interface SQLExpress<T> {
 
+    Logger logger = LoggerFactory.getLogger(SQLExpress.class);
+    /**
+     * 数据库方言
+     */
+    int DIALECT_MYSQL = 1;
+    int DIALECT_MSSQL = 2;
+    int DIALECT_ORACLE = 3;
+    int DIALECT_PGSQL = 4;
+
+    String[] BASE_IGNORE = {"createAt", "updateAt", "createBy", "updateBy"};
+
+    String DEFAULT_MKF = "id";
+
     T toSQL();
 
+    int dialect = DIALECT_PGSQL;
+
 
     default String getComma() {
+        switch (dialect) {
+            case DIALECT_MYSQL -> {
+                return "`";
+            }
+            case DIALECT_MSSQL -> {
+                return "'";
+            }
+            case DIALECT_ORACLE -> {
+                return "\"";
+            }
+            case DIALECT_PGSQL -> {
+                return "\"";
+            }
+            default -> {
+            }
+        }
+
         return "\"";
     }
 
     boolean strict = false;
 
 
+    /**
+     * 获取主键字段名
+     *
+     * @param query
+     * @param where
+     * @return
+     */
+    default String getMkf(BasicQuery query, OBuilder.Where where) {
+        String fieldName = where.key;
+        if (DbUtil.isEmptyOrNull(fieldName)) {
+            if (!DbUtil.isEmptyOrNull(where.sql)) {
+                logger.warn("SQL#builder with sql foreign key is not support yet! {}", where.sql);
+            }
+            return null;
+        }
+        try {
+            //info
+            Class<?> infoClz = query.getClass().getAnnotation(QE.class).clz();
+            Field field = infoClz.getField(DbUtil.getCamelName(fieldName));
+            if (field.isAnnotationPresent(One.class)) {
+                One one = field.getAnnotation(One.class);
+                where.key = one.tf();
+                return one.mkf();
+            }
+        } catch (NoSuchFieldException e) {
+            try {
+                //query
+                Field field = query.getClass().getField(DbUtil.getCamelName(fieldName));
+                if (field.isAnnotationPresent(QF.class)) {
+                    QF qf = field.getAnnotation(QF.class);
+                    where.key = qf.tf();
+                    return qf.pkf();
+                }
+            } catch (NoSuchFieldException e1) {
+                return null;
+            }
+        }
+        return null;
+    }
+
+
+    /**
+     * 获取外键关联实体类
+     */
+    default Class<?> getFkDomainClass(Field f, Class<?> domainClass) {
+        try {
+            if (f.isAnnotationPresent(FK.class)) {
+                return f.getAnnotation(FK.class).clz();
+            }
+            if (f.isAnnotationPresent(One.class)) {
+                One oneAnnotation = f.getAnnotation(One.class);
+                if (null != oneAnnotation) {
+                    if (oneAnnotation.te() != void.class) {
+                        return oneAnnotation.te();
+                    }
+                    if (!DbUtil.isEmptyOrNull(oneAnnotation.mkf())) {
+                        if (DbUtil.isGenericType(f.getType())) {
+                            Field field = domainClass.getDeclaringClass().getDeclaredField(oneAnnotation.mkf());
+                            if (field.isAnnotationPresent(FK.class)) {
+                                return field.getAnnotation(FK.class).clz();
+                            }
+                        } else {
+                            return f.getDeclaringClass();
+                        }
+                    }
+                }
+            }
+            if (f.isAnnotationPresent(QF.class)) {
+                QF qf = f.getAnnotation(QF.class);
+                if (!DbUtil.isEmptyOrNull(qf.pkf())) {
+                    Field field = domainClass.getDeclaringClass().getDeclaredField(qf.pkf());
+                    return field.getAnnotation(FK.class).clz();
+                }
+            }
+        } catch (NoSuchFieldException e) {
+            logger.error("SQL2Helper ERR# getFkDomainClass ,fileName:{},class:{}", f.getName(), domainClass.getSimpleName());
+        }
+        return Void.class;
+    }
+
+
     default void appendValue(StringBuilder sbr, Type type, Object value, List<Object> parameters) {
         sbr.append("?").append(",");
         parameters.add(value);
@@ -63,6 +183,13 @@ public interface SQLExpress<T> {
         return JdbcHelper.tbPrefix + DbUtil.getColumnName(tbName);
     }
 
+    default String getTableName(String tbName) {
+        if (tbName.endsWith("Info")) {
+            tbName = tbName.substring(0, tbName.length() - 4);
+        }
+        return JdbcHelper.getTbPrefix() + DbUtil.getColumnName(tbName);
+    }
+
     default String getTableName(Entity anno) {
         String tbName = anno.tbName();
         if (!DbUtil.isEmptyOrNull(tbName)) {

+ 933 - 0
car-wash-jdbc/src/main/java/com/kym/jdbc/express/SelectSQLExpress.java

@@ -1,14 +1,37 @@
 package com.kym.jdbc.express;
 
+import com.kym.DbUtil;
+import com.kym.JacksonUtil;
+import com.kym.jdbc.BasicQuery;
+import com.kym.jdbc.IHandler;
+import com.kym.jdbc.OBuilder;
 import com.kym.jdbc.OBuilder.Where;
 import com.kym.jdbc.SQLEntity;
+import com.kym.jdbc.annotations.DBF;
+import com.kym.jdbc.annotations.Entity;
+import com.kym.jdbc.annotations.FK;
 import com.kym.jdbc.annotations.JoinType;
+import com.kym.jdbc.annotations.Many;
+import com.kym.jdbc.annotations.OP;
+import com.kym.jdbc.annotations.One;
+import com.kym.jdbc.annotations.QE;
+import com.kym.jdbc.annotations.QF;
+import com.kym.jdbc.annotations.QueryType;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
 import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
 
 
 /**
@@ -50,9 +73,919 @@ public class SelectSQLExpress implements SQLExpress<SQLEntity> {
     private final List<String> groups = new ArrayList<>();
 
 
+    private int dialect = SQLExpress.DIALECT_MYSQL;
+
+    public SelectSQLExpress(int dialect) {
+        this.dialect = dialect;
+    }
+
     @Override
     public SQLEntity toSQL() {
         //TODO
         return null;
     }
+
+
+
+    /**
+     * 聚合函数查询<p>
+     * 注意:聚合函数的查询需要使用子查询</p>
+     *
+     * @param clz
+     * @param func    聚合查询字段 count(1) sum(amt)
+     * @param builder
+     * @return
+     */
+    public SQLEntity selectFunc(Class<?> clz, String func, OBuilder builder) {
+        SQLEntity entity = new SQLEntity();
+        List<Object> parameters = new ArrayList<>(16);
+        boolean distinct = distinctAggerate(func);
+        StringBuilder sbr = new StringBuilder();
+        boolean originEntity = !clz.getSimpleName().endsWith("Info");
+        if (originEntity) {
+            String funcField = func;
+            if (!distinct) {
+                funcField = func.contains("COUNT(") ? "1" : func.trim().split("\\(")[1].split("\\)")[0].trim();
+            }
+            sbr.append("SELECT ").append(funcField).append(" FROM ").append(getTableName(clz, clz.getSimpleName()));
+            if (null != builder) {
+                if (!DbUtil.isEmptyOrNull(builder.getWheres())) {
+                    List<Where> wheres = builder.getWheres();
+                    if (!DbUtil.isEmptyOrNull(wheres)) {
+                        sbr.append(" \r\n WHERE 1=1");
+                        wheres.forEach(wh -> {
+                            sbr.append(" AND ");
+                            appendBuilderWhere(sbr, wh, "", parameters);
+                        });
+                    }
+                }
+                //GROUP BY
+                if (!DbUtil.isEmptyOrNull(builder.getGroupBys())) {
+                    sbr.append("  \r\n GROUP BY ");
+                    builder.getGroupBys().forEach(group -> {
+                        sbr.append(group).append(" ,");
+                    });
+                    sbr.deleteCharAt(sbr.length() - 1);
+                }
+                //ORDER BY
+                if (!DbUtil.isEmptyOrNull(builder.getOrderBys())) {
+                    sbr.append(" ORDER BY ");
+                    builder.getOrderBys().forEach(order -> sbr.append(order).append(" ,"));
+                    sbr.deleteCharAt(sbr.length() - 1);
+                }
+
+                //count不分页
+                if (!func.contains("COUNT(")) {
+                    //分页
+                    String result = appendWhereLimit(builder, sbr);
+                    if (null != result) {
+                        if (!distinct) {
+                            entity.sql = "SELECT " + func + " FROM (" + result + ") temp";
+                        } else {
+                            entity.sql = result;
+                        }
+                    }
+                }
+            }
+            if (!distinct) {
+                entity.sql = "SELECT " + func + " FROM (" + sbr.toString() + ") temp";
+            } else {
+                entity.sql = sbr.toString();
+            }
+        } else {
+            //支持聚合查询的关联
+            String queryDomain = clz.getSuperclass().getCanonicalName() + "$" + clz.getSuperclass().getSimpleName() + "BasicQuery";
+            try {
+                Object obj = Class.forName(queryDomain).newInstance();
+                if (!DbUtil.isEmptyOrNull(func)) {
+                    DbUtil.setFieldValue(obj, obj.getClass().getField("pageSize"), -1);
+                }
+                return select((BasicQuery) obj, builder, null, null, func, true);
+            } catch (InstantiationException | IllegalAccessException | ClassNotFoundException | NoSuchFieldException e) {
+                logger.error("SQL2Helper ERR# initialize class,class:{}", queryDomain);
+                throw new IllegalStateException(e);
+            }
+
+        }
+        entity.parameters = parameters.toArray();
+        return entity;
+    }
+
+
+
+    public SQLEntity selectListByWhereV2(Class<?> clz, OBuilder builder, List<String> include, List<String> exclude, String aggregate, boolean isList) {
+        SQLEntity sqlEntity = new SQLEntity();
+        List<Object> parameters = new ArrayList<>();
+        Set<Field> fields = DbUtil.getEntityFields(clz);
+        boolean isSimple = !clz.getSimpleName().endsWith("Info");
+        if (isSimple) {
+            Entity entity = clz.getAnnotation(Entity.class);
+            StringBuilder sbr = new StringBuilder();
+            if (!DbUtil.isEmptyOrNull(aggregate)) {
+                sbr.append("SELECT ").append(aggregate).append(" FROM ").append(getTableName(entity));
+            } else {
+                if (DbUtil.isEmptyOrNull(include)) {
+                    if (DbUtil.isEmptyOrNull(exclude)) {
+                        sbr.append("SELECT * FROM ").append(getTableName(entity));
+                    } else {
+                        sbr.append("SELECT ");
+                        for (Field field : fields) {
+                            if (DbUtil.isUsageField(field)) {
+                                //richId  rich2Id 不关联查
+                                String fileName = field.getName();
+                                if (!exclude.contains(fileName)) {
+                                    sbr.append(getComma()).append(DbUtil.getColumnName(fileName)).append(getComma()).append(" ,");
+                                }
+                            }
+                        }
+                        sbr.deleteCharAt(sbr.length() - 1);
+                        sbr.append("  \n FROM ").append(getTableName(entity));
+                    }
+                } else {
+                    sbr.append("SELECT ");
+                    for (Field field : fields) {
+                        if (DbUtil.isUsageField(field)) {
+                            String fileName = field.getName();
+                            if (include.contains(fileName)) {
+                                sbr.append(getComma()).append(DbUtil.getColumnName(fileName)).append(getComma()).append(" ,");
+                            }
+                        }
+                    }
+                    sbr.deleteCharAt(sbr.length() - 1);
+                    sbr.append("  \n FROM ").append(getTableName(entity));
+                }
+            }
+            if (null != builder && !DbUtil.isEmptyOrNull(builder.getWheres())) {
+                List<Where> wheres = builder.getWheres();
+                if (!DbUtil.isEmptyOrNull(wheres)) {
+                    sbr.append(" \r\n WHERE 1=1");
+                    wheres.forEach(wh -> {
+                        sbr.append(" AND ");
+                        appendBuilderWhere(sbr, wh, "", parameters);
+                    });
+                }
+            }
+
+
+            if (isList) {
+                //ORDER BY
+                if (null != builder && !DbUtil.isEmptyOrNull(builder.getOrderBys())) {
+                    sbr.append(" ORDER BY ");
+                    builder.getOrderBys().forEach(order -> sbr.append(order).append(" ,"));
+                    sbr.deleteCharAt(sbr.length() - 1);
+                } else {
+                    sbr.append(" ORDER BY update_at DESC ");
+                }
+
+                //limit
+                String result = appendWhereLimit(builder, sbr);
+                if (null != result) {
+                    sqlEntity.sql = result;
+                }
+            }
+
+            sbr.append(";");
+            sqlEntity.sql = sbr.toString();
+        } else {
+            String queryDomain = clz.getSuperclass().getCanonicalName() + "$" + clz.getSuperclass().getSimpleName() + "BasicQuery";
+            Object obj;
+            try {
+                obj = Class.forName(queryDomain).getDeclaredConstructor().newInstance();
+                if (!DbUtil.isEmptyOrNull(aggregate)) {
+                    DbUtil.setFieldValue(obj, obj.getClass().getField("pageSize"), -1);
+                }
+            } catch (InstantiationException | IllegalAccessException | ClassNotFoundException | NoSuchFieldException e) {
+                logger.error("SQL2Helper ERR# initialize class,class:{}", queryDomain);
+                throw new IllegalStateException(e);
+            } catch (InvocationTargetException | NoSuchMethodException e) {
+                throw new RuntimeException(e);
+            }
+            return select((BasicQuery) obj, builder, include, exclude, aggregate, isList);
+        }
+        sqlEntity.parameters = parameters.toArray();
+        return sqlEntity;
+    }
+
+
+
+    /**
+     * 查询SQL解析生成
+     *
+     * @param query     query条件对象
+     * @param builder   where条件对象
+     * @param include   指定查询字段集合
+     * @param exclude   指定过滤不查询字段集合
+     * @param aggregate 聚合查询条件
+     */
+    public SQLEntity select(BasicQuery query, OBuilder builder, List<String> include, List<String> exclude, String aggregate, boolean isList) {
+        SQLEntity sqlEntity = new SQLEntity();
+        List<Object> parameters = new ArrayList<>(32);
+        if (!DbUtil.isEmptyOrNull(query.includeFields)) {
+            if (DbUtil.isEmptyOrNull(include)) {
+                include = new ArrayList<>();
+            }
+            for (String includeField : query.includeFields) {
+                if (!include.contains(includeField)) {
+                    include.add(includeField);
+                }
+            }
+        }
+        if (!DbUtil.isEmptyOrNull(query.excludeFields)) {
+            if (DbUtil.isEmptyOrNull(exclude)) {
+                exclude = new ArrayList<>();
+            }
+            for (String excludeField : query.excludeFields) {
+                if (!exclude.contains(excludeField)) {
+                    exclude.add(excludeField);
+                }
+            }
+        }
+        StringBuilder sbr = new StringBuilder();
+        int aliasIdx = 0;
+        //表别名 @QF->inner @FK、@One->left
+        Map<String, String> alias = new HashMap<>(4);
+        //关联表名
+        Map<String, String> tbs = new HashMap<>(4);
+        QE qEAnnotation = query.getClass().getAnnotation(QE.class);
+        String queryClassName = query.getClass().getSimpleName();
+        if (null == qEAnnotation) {
+            throw new IllegalStateException("query entity of " + queryClassName + " @Query Entity is not defined!");
+        }
+        Class<?> infoClass = qEAnnotation.clz();
+        Entity entity = infoClass.getSuperclass().getAnnotation(Entity.class);
+//        Field[] fields = infoClass.getFields();
+        Set<Field> fields = DbUtil.getEntityFields(infoClass);
+        Set<Field> qfields = DbUtil.getQueryFields(query.getClass());
+//        Field[] qfields = query.getClass().getFields();
+        //关联表别名
+        //------1.查询字段
+        for (Field field : fields) {
+            String fieldName = field.getName();
+            //常量字段过滤
+            if (!DbUtil.isUsageField(field)) {
+                continue;
+            }
+            One oneAnnotation = field.getAnnotation(One.class);
+            Many manyAnnotation = field.getAnnotation(Many.class);
+            boolean isExtenstionField = null != oneAnnotation || null != manyAnnotation;
+            //忽略字段过滤
+            if (!DbUtil.isEmptyOrNull(exclude) && exclude.contains(fieldName) && !isExtenstionField) {
+                continue;
+            }
+            //指定查询
+            if (!DbUtil.isEmptyOrNull(include) && !include.contains(fieldName) && !isExtenstionField) {
+                continue;
+            }
+            DBF DBFAnnotation = field.getAnnotation(DBF.class);
+            if (null != DBFAnnotation) {
+                FK foreignKey = field.getAnnotation(FK.class);
+                if (null != foreignKey) {
+                    Class<?> entityClass = foreignKey.clz();
+                    Entity ey = entityClass.getAnnotation(Entity.class);
+                    for (Field qfield : qfields) {
+                        if (qfield.isAnnotationPresent(QF.class)) {
+                            QF qf = qfield.getAnnotation(QF.class);
+                            String mkf = qf.pkf();
+                            if (!DbUtil.isEmptyOrNull(mkf) && mkf.equals(fieldName)) {
+                                if (null != DbUtil.getFieldValue(query, qfield)) {
+                                    alias.putIfAbsent(fieldName, "i" + aliasIdx++);
+                                    tbs.putIfAbsent(fieldName, getTableName(ey));
+                                }
+                            }
+                        }
+                    }
+                    alias.putIfAbsent(fieldName, "l" + aliasIdx++);
+                    tbs.putIfAbsent(fieldName, getTableName(ey));
+                }
+            } else {
+                if (null != oneAnnotation) {
+                    String mkf = oneAnnotation.mkf();
+                    if (!DbUtil.isGenericType(field.getType()) && DEFAULT_MKF.equals(mkf)) {
+                        mkf = fieldName;
+                    }
+                    JoinType joinType = oneAnnotation.join();
+                    if (JoinType.LEFT == joinType) {
+                        alias.put(mkf, "l" + aliasIdx++);
+                    } else if (JoinType.INNER == joinType) {
+                        alias.put(mkf, "i" + aliasIdx++);
+                    } else if (JoinType.RIGHT == joinType) {
+                        alias.put(mkf, "r" + aliasIdx++);
+                    }
+                }
+            }
+        }
+        //非聚合查询
+        if (DbUtil.isEmptyOrNull(aggregate)) {
+            sbr.append("SELECT");
+            //------1.查询主表字段
+            boolean appendFields = false;
+            for (Field field : fields) {
+                String fieldName = field.getName();
+                //常量字段过滤
+                if (!DbUtil.isUsageField(field)) {
+                    continue;
+                }
+                boolean isExtenstionField = field.isAnnotationPresent(One.class) || field.isAnnotationPresent(Many.class);
+                //忽略字段过滤
+                if (!DbUtil.isEmptyOrNull(exclude) && exclude.contains(fieldName) && !isExtenstionField) {
+                    continue;
+                }
+                //指定查询
+                if (!DbUtil.isEmptyOrNull(include) && !include.contains(fieldName) && !isExtenstionField) {
+                    continue;
+                }
+                DBF DBFAnnotation = field.getAnnotation(DBF.class);
+                if (null != DBFAnnotation) {
+                    if (appendFields) {
+                        sbr.append(",");
+                    }
+                    sbr.append(" l.").append(getComma()).append(DbUtil.getColumnName(fieldName)).append(getComma());
+                    appendFields = true;
+                }
+            }
+            //-------2.查询关联字段
+            for (Field field : fields) {
+                Class<?> type = field.getType();
+                String fieldName = field.getName();
+                //常量字段过滤
+                if (!DbUtil.isUsageField(field)) {
+                    continue;
+                }
+                boolean isExtenstionField = field.isAnnotationPresent(One.class) || field.isAnnotationPresent(Many.class);
+                //忽略字段过滤
+                if (!DbUtil.isEmptyOrNull(exclude) && exclude.contains(fieldName)) {
+                    continue;
+                }
+                //指定查询
+                if (!DbUtil.isEmptyOrNull(include) && !include.contains(fieldName)) {
+                    continue;
+                }
+                Class<?> fieldClass = field.getType();
+                One oneAnnotation = field.getAnnotation(One.class);
+                if (null != oneAnnotation) {
+                    //忽略查询
+                    if (oneAnnotation.noQuery()) {
+                        continue;
+                    }
+                    String fkField = oneAnnotation.mkf();
+                    if (!DbUtil.isGenericType(field.getType()) && DEFAULT_MKF.equals(fkField)) {
+                        fkField = fieldName;
+                    }
+                    // join字段
+                    if (!DbUtil.isEmptyOrNull(fkField)) {
+                        //1.join查询对象
+                        if (!DbUtil.isGenericType(type) && type != String.class && !type.isArray() && !type.isAssignableFrom(List.class)) {
+//                            alias.putIfAbsent(fkField, "l" + aliasIdx++);
+                            Field[] joinFields = fieldClass.getFields();
+                            for (Field joinField : joinFields) {
+                                if (DbUtil.isUsageField(joinField)) {
+                                    if (!"SELECT".contentEquals(sbr)) {
+                                        sbr.append(",");
+                                    }
+                                    sbr.append(alias.get(fkField)).append(".").append(getComma()).append(DbUtil.getColumnName(joinField.getName())).append(getComma()).append(" AS ").append(getComma()).append(fieldName).append("_").append(DbUtil.getColumnName(joinField.getName())).append(getComma());
+                                }
+                            }
+
+                            //2.join查询变量
+                        } else {
+                            if (!"SELECT".equals(sbr.toString().trim())) {
+                                sbr.append(",");
+                            }
+                            sbr.append(alias.get(fkField)).append(".").append(getComma()).append(DbUtil.getColumnName(oneAnnotation.tf())).append(getComma()).append(" AS ").append(getComma()).append(DbUtil.getColumnName(fieldName)).append(getComma());
+                        }
+                    }
+                }
+            }
+        } else {
+           /* //聚合查询需要获取关联表别名
+            for (Field field : fields) {
+                if (field.isAnnotationPresent(Fk.class)) {
+                    alias.putIfAbsent(field.getName(), "l" + aliasIdx++);
+                }
+            }*/
+
+            String aggregateField = aggregate;
+            boolean distinct = distinctAggerate(aggregate);
+            if (!distinct) {
+                aggregateField = aggregate.contains("COUNT(") ? "1" : aggregate.trim().split("\\(")[1].split("\\)")[0].trim();
+            }
+            sbr.append("SELECT ").append(aggregateField);
+        }
+
+        sbr.append("   \n FROM ").append(getComma()).append(getTableName(entity)).append(getComma()).append(" AS l");
+        List<String> joined = new ArrayList<>();
+        //-------3.关联对象  JOINS
+        //BUG:涉及到关联查询的对象字段需要inner join @QF
+//        Field[] qfs =dbu query.getClass().getDeclaredFields();
+        for (Field qf : qfields) {
+            //qf 内联查询
+            if (qf.isAnnotationPresent(QF.class)) {
+                Object val = DbUtil.getFieldValue(query, qf);
+                if (null != val) {
+                    String amkf = qf.getAnnotation(QF.class).pkf();
+                    if (!DbUtil.isEmptyOrNull(amkf)) {
+//                        if (!joinFields.contains(amkf)) {
+//                            joinFields.add(amkf);
+//                            alias.putIfAbsent(amkf, "i" + aliasIdx++);
+                        if (!joined.contains(alias.get(amkf))) {
+                            joined.add(alias.get(amkf));
+                        } else {
+                            continue;
+                        }
+                        Class<?> aliasClass = getFkDomainClass(qf, infoClass);
+                        sbr.append(" INNER JOIN ").append(getTableName(aliasClass, aliasClass.getSimpleName())).append(" AS ").append(alias.get(amkf)).append(" ON ").append("l.").append(getComma()).append(DbUtil.getColumnName(amkf)).append(getComma()).append("=").append(alias.get(amkf)).append(".").append(getComma()).append(DbUtil.getColumnName(qf.getAnnotation(QF.class).tkf())).append(getComma());
+                    }
+                }
+//                }
+            }
+        }
+        for (Field field : fields) {
+            String fieldName = field.getName();
+            //忽略查询
+            if (!DbUtil.isEmptyOrNull(exclude) && exclude.contains(fieldName)) {
+                continue;
+            }
+            One oneAnnotation = field.getAnnotation(One.class);
+            if (null != oneAnnotation) {
+                //忽略查询
+                if (oneAnnotation.noQuery()) {
+                    continue;
+                }
+                if (!DbUtil.isUsageField(field)) {
+                    continue;
+                }
+                String mkf = oneAnnotation.mkf();
+                if (!DbUtil.isGenericType(field.getType()) && DEFAULT_MKF.equals(mkf)) {
+                    mkf = fieldName;
+                }
+                //joins
+                if (!DbUtil.isEmptyOrNull(mkf)) {
+                    if (!joined.contains(alias.get(mkf))) {
+                        joined.add(alias.get(mkf));
+                    } else {
+                        continue;
+                    }
+//                    joinFields.add(fkField);
+                    Class<?> aliasClass = getFkDomainClass(field, infoClass);
+//                    alias.putIfAbsent(fkField, "l" + aliasIdx++);
+                    if (oneAnnotation.join() == JoinType.LEFT) {
+                        sbr.append(" \n LEFT JOIN ");
+                    } else if (oneAnnotation.join() == JoinType.INNER) {
+                        sbr.append("  \n  INNER JOIN  ");
+                    } else {
+                        sbr.append("  \n RIGHT JOIN ");
+                    }
+                    sbr.append(getTableName(aliasClass, aliasClass.getSimpleName())).append(" AS ").append(alias.get(mkf)).append(" ON ").append("l.").append(getComma()).append(DbUtil.getColumnName(oneAnnotation.mkf())).append(getComma()).append("=").append(alias.get(mkf)).append(".").append(getComma()).append(DbUtil.getColumnName(oneAnnotation.tkf())).append(getComma());
+                }
+            }
+        }
+        //-------4.查询条件
+        sbr.append(" \n WHERE 1=1 ");
+        Field[] queryFields = query.getClass().getDeclaredFields();
+        //query条件和Builder条件仅支持一个(查询时只提供一个条件构造实体)
+        if (null != builder && !DbUtil.isEmptyOrNull(builder.getWheres())) {
+            List<Where> wheres = builder.getWheres();
+            wheres.forEach(wh -> {
+                //联表查询字段
+                String aliasName = alias.getOrDefault(getMkf(query, wh), "l");
+                sbr.append(" AND ");
+                appendBuilderWhere(sbr, wh, aliasName, parameters);
+            });
+        } else {
+            for (Field qf : queryFields) {
+                Object val = DbUtil.getFieldValue(query, qf);
+                String fieldName = qf.getName();
+                if (DbUtil.isEmptyOrNull(val)) {
+                    continue;
+                }
+                QF qfAnnotation = qf.getAnnotation(QF.class);
+                if (null == qfAnnotation) {
+                    if (!fieldName.endsWith("Sort")) {
+                        sbr.append(" AND l.").append(getComma()).append(DbUtil.getColumnName(fieldName)).append(getComma());
+                        if (String.class.equals(qf.getType())) {
+                            if (DIALECT_MYSQL == dialect) {
+                                sbr.append(" LIKE concat('%',?,'%')");
+                            } else if (DIALECT_PGSQL == dialect) {
+                                sbr.append(" like concat('%',?::text,'%')");
+                            } else if (DIALECT_MSSQL == dialect) {
+                                sbr.append(" LIKE '%'+?+'%')");
+                            } else if (DIALECT_ORACLE == dialect) {
+                                sbr.append(" LIKE '%'||?||'%')");
+                            }
+                            parameters.add(val);
+                        } else {
+                            sbr.append(" = ?");
+                            parameters.add(val);
+//                            .append(val);
+                        }
+                    }
+                } else {
+                    //foreignKeys
+                    String mkf = qfAnnotation.pkf();
+                    if (qfAnnotation.qt() == QueryType.IGNORE) {
+                        continue;
+                    }
+                    if (!DbUtil.isEmptyOrNull(mkf)) {
+                        String tf = qfAnnotation.tf();
+                        if (DbUtil.isEmptyOrNull(tf)) {
+                            logger.error("SQL2Helper ERR# [" + fieldName + "] @QF with mkf define,but without tkf exist!!!");
+                        } else {
+                            if (qfAnnotation.qt() == QueryType.MAIN) {
+                                sbr.append(" AND ").append(" l").append(".").append(getComma()).append(DbUtil.getColumnName(mkf)).append(getComma());
+                            } else {
+                                sbr.append(" AND ").append(alias.get(mkf)).append(".").append(getComma()).append(DbUtil.getColumnName(tf)).append(getComma());
+                            }
+                            //字符串使用模糊查询
+                            if (String.class.equals(qf.getType())) {
+                                if (DIALECT_MYSQL == dialect) {
+                                    sbr.append(" like concat('%',?,'%')");
+                                } else if (DIALECT_PGSQL == dialect) {
+                                    sbr.append(" like concat('%',?::text,'%')");
+                                } else if (DIALECT_MSSQL == dialect) {
+                                    sbr.append(" like '%'+'?'+'%')");
+                                } else if (DIALECT_ORACLE == dialect) {
+                                    sbr.append(" like '%'||'?'||'%')");
+                                }
+                                parameters.add(val);
+                            } else {
+                                sbr.append(" =");
+//                                parameters.add(val);
+                                getValue(sbr, val, parameters);
+                            }
+                        }
+
+                    }
+                    //sql
+                    String whereSql = qfAnnotation.sql();
+                    String tbAlias = alias.getOrDefault(qfAnnotation.pkf(), "l");
+                    whereSql = appendWhereSql(whereSql, Collections.singletonList(val), tbAlias, parameters);
+                    if (!DbUtil.isEmptyOrNull(whereSql)) {
+                        sbr.append(" AND ").append(whereSql);
+                    }
+                    //op
+                    String operator = qfAnnotation.op();
+                    if (!DbUtil.isEmptyOrNull(operator)) {
+                        String tf = qfAnnotation.tf();
+                        if (DbUtil.isEmptyOrNull(tf)) {
+                            logger.error("SQL2Helper ERR# " + fieldName + "@QF with operator defined,but without tkf exist!!!");
+                        } else {
+                            //JIN  JINT
+                            if (operator.equals(OP.JIN)) {
+                                int loop = 1;
+                                String each = qfAnnotation.each();
+                                if (val instanceof Collection<?>) {
+                                    List<Object> list = JacksonUtil.toList(val);
+                                    loop = list.size();
+
+                                    parameters.addAll((Collection<?>) val);
+                                } else if (val.getClass().isArray()) {
+                                    loop = Array.getLength(val);
+                                    for (int i = 0; i < loop; i++) {
+                                        parameters.add(Array.get(val, i));
+                                    }
+                                } else {
+                                    loop = 1;
+                                    parameters.add(val);
+                                }
+                                // and ( json_contains(l.id_list,'1'))
+                                if (dialect == IHandler.DIALECT_MYSQL) {
+                                    sbr.append(" AND ").append("( ");
+                                    for (int i = 0; i < loop; i++) {
+                                        sbr.append(" (JSON_CONTAINS(").append(tbAlias).append(".").append(getComma()).append(DbUtil.getColumnName(tf)).append(getComma()).append(",").append("JSON_ARRAY(?)) ");
+                                        if (i != loop - 1) {
+                                            sbr.append(each);
+                                        }
+                                    }
+                                    sbr.append(") ");
+                                    //  owner_id_list::jsonb @> jsonb_build_array(2)
+                                    //  owner_id_list::jsonb @> '[2]'
+                                } else if (dialect == IHandler.DIALECT_PGSQL) {
+                                    sbr.append(" AND ").append("( ");
+                                    for (int i = 0; i < loop; i++) {
+                                        sbr.append(" (").append(tbAlias).append(".").append(getComma()).append(DbUtil.getColumnName(tf)).append(getComma()).append("::jsonb @>  ").append("jsonb_build_array(?)) ");
+                                        if (i != loop - 1) {
+                                            sbr.append(each);
+                                        }
+                                    }
+                                    sbr.append(") ");
+                                }
+
+                            } else if (operator.equals(OP.JINT)) {
+
+                                //and (JSON_OVERLAPS(role,'["a","d"]')=1)
+                                if (dialect == IHandler.DIALECT_MYSQL) {
+                                    sbr.append(" AND ").append("(").append(operator).append("JSON_OVERLAPS(").append(tbAlias).append(".").append(getComma()).append(DbUtil.getColumnName(tf)).append(getComma()).append(",").append("'?')=1").append(")");
+                                    parameters.add(JacksonUtil.toJSONString(val));
+                                } else if (dialect == IHandler.DIALECT_PGSQL) {
+                                    //    //ARRAY[1,4,3] && ARRAY[2,1]
+                                    sbr.append(" AND ").append("(").append(tbAlias).append(".").append(getComma()).append(DbUtil.getColumnName(tf)).append(getComma()).append("::jsonb && ").append("jsonb_build_array(?))");
+                                    parameters.add(JacksonUtil.toJSONString(val));
+                                }
+                            } else if (operator.equals(OP.IN) || operator.equals(OP.NIN)) {
+                                sbr.append(" AND ").append("(").append(tbAlias).append(".").append(getComma()).append(DbUtil.getColumnName(tf)).append(getComma()).append(" ").append(operator).append("  (");
+                                if (val instanceof Collection<?>) {
+                                    List<Object> list = JacksonUtil.toList(val);
+                                    String collect = list.stream().map(k -> "?").collect(Collectors.joining(","));
+                                    sbr.append(collect).append(") ) ");
+                                    parameters.addAll((Collection<?>) val);
+                                } else if (val.getClass().isArray()) {
+                                    int length = Array.getLength(val);
+                                    for (int i = 0; i < length; i++) {
+                                        sbr.append("?");
+                                        if (i != length - 1) {
+                                            sbr.append(",");
+                                        }
+                                        parameters.add(Array.get(val, i));
+                                    }
+                                    sbr.append("))");
+                                } else {
+                                    throw new IllegalArgumentException("不支持的参数格式");
+                                }
+
+                            } else if (operator.equals(OP.RLK) || operator.equals(OP.LK) || operator.equals(OP.LLK)) {
+                                sbr.append(" AND ").append(tbAlias).append(".").append(getComma()).append(DbUtil.getColumnName(tf)).append(getComma()).append(" ").append(operator);
+                                parameters.add(val);
+                            } else {
+                                sbr.append(" AND ").append(tbAlias).append(".").append(getComma()).append(DbUtil.getColumnName(tf)).append(getComma()).append(" ").append(operator);
+                                if (qf.getType().isArray()) {
+                                    sbr.append(" (");
+                                    int length = Array.getLength(val);
+                                    for (int i = 0; i < length; i++) {
+                                        Object value = Array.get(val, i);
+                                        getValue(sbr, value, parameters);
+                                        if (i != length - 1) {
+                                            sbr.append(",");
+                                        }
+                                    }
+                                    sbr.append(")");
+                                } else if (val instanceof Collection<?>) {
+                                    List<Object> list = JacksonUtil.toList(val);
+                                    String collect = list.stream().map(k -> "?").collect(Collectors.joining(","));
+                                    sbr.append(collect).append(")  ");
+                                    parameters.addAll((Collection<?>) val);
+                                } else {
+                                    getValue(sbr, val, parameters);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+
+        //-------6.GROUP BY
+        if (null != builder && !DbUtil.isEmptyOrNull(builder.getGroupBys())) {
+            sbr.append(" GROUP BY ");
+            builder.getGroupBys().forEach(group -> {
+                sbr.append(group).append(" ,");
+            });
+            sbr.deleteCharAt(sbr.length() - 1);
+        }
+
+        //-------5.having
+        //todo
+
+        //-------7.ORDER BY(query)
+        boolean ordered = false;
+        //聚合查询不需要排序
+        if (DbUtil.isEmptyOrNull(aggregate) && isList) {
+            //多个排序字段需要确定先后顺序
+            Map<Integer, String> sortMap = new HashMap<>(16);
+            if (DbUtil.isEmptyOrNull(query.sortFields)) {
+                for (Field qf : queryFields) {
+                    Object val = DbUtil.getFieldValue(query, qf);
+                    if (null == val) {
+                        continue;
+                    }
+                    int sortValue = 0;
+                    if (val instanceof Integer) {
+                        sortValue = (int) val;
+                    }
+                    if (sortValue == 0) {
+                        continue;
+                    }
+                    String fieldName = qf.getName();
+
+                    List<Field> sorted = new ArrayList<>();
+                    QF qfAnnotation = qf.getAnnotation(QF.class);
+                    if (null == qfAnnotation) {
+                        if (fieldName.endsWith("Sort")) {
+                            if (!ordered) {
+                                ordered = true;
+                                sbr.append(" ORDER BY ");
+                            }
+
+//                            sbr.append(" l.")
+//                                    .append(getComma())
+//                                    .append(DbUtil.getColumnName(fieldName.substring(0, fieldName.length() - 4)))
+//                                    .append(getComma());
+                            if (sortValue % 2 == BasicQuery.SORT_ASC) {
+                                sortMap.put(sortValue, String.format("%s ASC ", DbUtil.getColumnName(fieldName.substring(0, fieldName.length() - 4))));
+//                                sbr.append(" ASC ,");
+                            } else {
+//                                sbr.append(" DESC ,");
+                                sortMap.put(sortValue, String.format("%s DESC ", DbUtil.getColumnName(fieldName.substring(0, fieldName.length() - 4))));
+                            }
+                        }
+                    }
+
+                    if (!DbUtil.isEmptyOrNull(sortMap)) {
+                        Set<Integer> integers = sortMap.keySet();
+                        List<Integer> sorts = new ArrayList<>(integers);
+                        sorts.sort(Comparator.comparingInt(o -> o));
+                        sbr.append(sorts.stream().map(k -> "l." + sortMap.get(k)).collect(Collectors.joining(",")));
+                    }
+               /*     if (null == qfAnnotation) {
+                        if (fieldName.endsWith("Sort")) {
+                            if (!ordered) {
+                                ordered = true;
+                                sbr.append(" ORDER BY ");
+                            }
+                            sbr.append(" l.")
+                                    .append(getComma())
+                                    .append(DbUtil.getColumnName(fieldName.substring(0, fieldName.length() - 4)))
+                                    .append(getComma());
+                            if (sortType == BasicQuery.SORT_ASC) {
+                                sbr.append(" ASC ,");
+                            } else if (sortType == BasicQuery.SORT_DESC) {
+                                sbr.append(" desc ,");
+                            }
+                        }
+                    }*/
+                }
+            } else {
+                String[] sorts = query.sortFields;
+                for (String sortField : sorts) {
+                    try {
+                        Field sf = query.getClass().getDeclaredField(sortField + "Sort");
+                        Object val = DbUtil.getFieldValue(query, sf);
+                        if (null == val) {
+                            continue;
+                        }
+                        int sortType = (int) val;
+                        if (!ordered) {
+                            ordered = true;
+                            sbr.append(" ORDER BY ");
+                        }
+
+                        sbr.append(" l.").append(getComma()).append(DbUtil.getColumnName(sortField)).append(getComma());
+                        if (sortType == BasicQuery.SORT_ASC) {
+                            sbr.append(" ASC ,");
+                        } else if (sortType == BasicQuery.SORT_DESC) {
+                            sbr.append(" DESC ,");
+                        }
+                    } catch (NoSuchFieldException e) {
+                        logger.warn("SQL2Helper warn# sort field is not exist,{}", sortField);
+                    }
+                }
+            }
+        }
+        //-------7.ORDER BY(builder)  聚合查询不需要排序
+        if (DbUtil.isEmptyOrNull(aggregate) && isList) {
+            if (null != builder && !DbUtil.isEmptyOrNull(builder.getOrderBys())) {
+                if (!ordered) {
+                    ordered = true;
+                    sbr.append(" ORDER BY ");
+                }
+                builder.getOrderBys().forEach(order -> sbr.append(" l.").append(order).append(" ,"));
+            }
+            if (ordered && sbr.toString().endsWith(",")) {
+                sbr.deleteCharAt(sbr.length() - 1);
+            }
+            //------7.ORDER BY default update_at DESC
+            if (!ordered) {
+                sbr.append(" ORDER BY l.update_at DESC");
+            }
+        }
+
+        //-------8.limit(query)
+        if (isList) {
+            if (query.pageSize > 0) {
+                if (DIALECT_MYSQL == dialect) {
+                    sbr.append(" LIMIT ");
+                    if (query.pageIndex > 0) {
+                        sbr.append((query.pageIndex - 1) * query.pageSize).append(",");
+                    }
+                    if (query.pageSize > 0) {
+                        sbr.append(query.pageSize);
+                    }
+                } else if (DIALECT_MSSQL == dialect) {
+                    sbr.append(" OFFSET ");
+                    if (query.pageIndex > 0) {
+                        sbr.append((query.pageIndex - 1) * query.pageSize).append(" ROWS ");
+                    }
+                    if (query.pageSize > 0) {
+                        sbr.append(" FETCH NEXT ").append(query.pageSize).append(" ROWS ONLY  ");
+                    }
+                } else if (DIALECT_PGSQL == dialect) {
+                    sbr.append(" LIMIT ").append(query.pageSize);
+                    if (query.pageIndex > 0) {
+                        sbr.append(" OFFSET ").append((query.pageIndex - 1) * query.pageSize);
+                    }
+                } else if (DIALECT_ORACLE == dialect) {
+                    StringBuilder sr = new StringBuilder();
+                    sr.append("SELECT * FROM (SELECT o.*,ROWNUM as rowno FROM (").append(sbr).append(") o ");
+                    if (query.pageSize > 0) {
+                        sr.append(" WHERE ROWNUM<=").append(query.pageSize).append(")  o1");
+                    }
+                    if (query.pageIndex > 0) {
+                        sr.append(" WHERE o1.rowno>").append((query.pageIndex - 1) * query.pageSize).append(";");
+                    }
+                    //聚合类使用子查询
+                    if (!DbUtil.isEmptyOrNull(aggregate)) {
+                        sqlEntity.sql = "SELECT " + aggregate + " FROM (" + sr.toString() + ") temp";
+                    }
+                    sqlEntity.sql = sr.toString();
+                }
+                //-------8.limit(builder)
+            } else {
+                String result = appendWhereLimit(builder, sbr);
+                if (null != result) {
+                    //聚合类使用子查询
+                    if (!DbUtil.isEmptyOrNull(aggregate) && !distinctAggerate(aggregate)) {
+                        sbr.setLength(0);
+                        sbr.append("SELECT ").append(aggregate).append(" FROM (").append(result).append(") temp");
+                    }
+                }
+            }
+
+        }
+
+        sqlEntity.sql = sbr.toString();
+        //聚合类使用子查询
+        if (!DbUtil.isEmptyOrNull(aggregate) && !distinctAggerate(aggregate)) {
+            String tmpSql = sbr.toString();
+            sbr.setLength(0);
+            sbr.append("SELECT ").append(aggregate).append(" FROM (").append(tmpSql).append(") temp");
+        }
+        sbr.append(";");
+
+        sqlEntity.sql = sbr.toString();
+        sqlEntity.parameters = parameters.toArray();
+        return sqlEntity;
+    }
+
+    private boolean distinctAggerate(String aggregate) {
+        return aggregate.toLowerCase().contains("distinct(");
+    }
+
+    private void getValue(StringBuilder sbr, Object value, List<Object> parameters) {
+        if (null != value) {
+            sbr.append("?");
+            parameters.add(value);
+        } else {
+            throw new IllegalArgumentException("append value with NULL");
+        }
+    }
+
+
+    private String appendWhereLimit(OBuilder OBuilder, StringBuilder sbr) {
+        if (null != OBuilder) {
+            if (OBuilder.limitDelta() > 0) {
+                if (DIALECT_MYSQL == dialect) {
+                    sbr.append(" LIMIT ");
+                    if (OBuilder.limitStart() > 0) {
+                        sbr.append(OBuilder.limitStart()).append(",");
+                    }
+                    if (OBuilder.limitDelta() > 0) {
+                        sbr.append(OBuilder.limitDelta());
+                    }
+                    return null;
+                } else if (DIALECT_MSSQL == dialect) {
+                    sbr.append(" OFFSET ");
+                    if (OBuilder.limitStart() >= 0) {
+                        sbr.append(OBuilder.limitStart()).append(" ROWS ");
+                    }
+                    if (OBuilder.limitDelta() > 0) {
+                        sbr.append(" FETCH NEXT  ").append(OBuilder.limitDelta()).append(" ROWS ONLY  ");
+                    }
+                    return null;
+                } else if (DIALECT_PGSQL == dialect) {
+                    sbr.append(" LIMIT ");
+
+                    if (OBuilder.limitDelta() > 0) {
+                        sbr.append(OBuilder.limitDelta());
+                    }
+                    if (OBuilder.limitStart() >= 0) {
+                        sbr.append(" OFFSET ").append(OBuilder.limitStart());
+                    }
+                    return null;
+                } else if (DIALECT_ORACLE == dialect) {
+                    StringBuilder sr = new StringBuilder();
+                    sr.append("SELECT * FROM (SELECT o.*,ROWNUM as rowno FROM (").append(sbr.toString()).append(") o ");
+                    if (OBuilder.limitDelta() > 0) {
+                        sr.append(" WHERE ROWNUM<=").append(OBuilder.limitDelta()).append(")  o1");
+                    }
+                    if (OBuilder.limitStart() >= 0) {
+                        sr.append(" WHERE o1.rowno>").append(OBuilder.limitStart());
+                    }
+                    return sr.toString();
+                }
+            }
+        }
+        return null;
+    }
+
+
 }

+ 233 - 2
car-wash-jdbc/src/main/java/com/kym/jdbc/express/UpdateSQLExpress.java

@@ -1,15 +1,246 @@
 package com.kym.jdbc.express;
 
+import com.kym.DbUtil;
+import com.kym.jdbc.OBuilder;
+import com.kym.jdbc.OBuilder.Where;
 import com.kym.jdbc.SQLEntity;
+import com.kym.jdbc.annotations.DBF;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
 
 
 /**
  * sql表达式 -update
  */
 public class UpdateSQLExpress implements SQLExpress<SQLEntity> {
+
+    private final Logger logger = LoggerFactory.getLogger(DeleteSQLExpress.class);
+
+    /**
+     * update  的表名
+     */
+    private String table;
+
+    /**
+     * 更新的列名
+     */
+    private List<String> cols = new ArrayList<>();
+
+    /**
+     * 更新的值
+     */
+    private List<Object> values = new ArrayList<>();
+
+    /**
+     * update 的条件
+     */
+    private List<Where> conditions = new ArrayList<>();
+
+    private int dialect = SQLExpress.DIALECT_MYSQL;
+
+    public UpdateSQLExpress(int dialect) {
+        this.dialect = dialect;
+    }
+
+
+    public UpdateSQLExpress() {
+    }
+
     @Override
     public SQLEntity toSQL() {
-        //TODO
-        return null;
+        if (DbUtil.isEmptyOrNull(cols)) {
+            throw new IllegalArgumentException("illegal update column, empty column");
+        }
+
+        if (DbUtil.isEmptyOrNull(conditions)) {
+            throw new IllegalArgumentException("illegal update column, empty condition");
+        }
+
+        SQLEntity entity = new SQLEntity();
+        StringBuilder sbr = new StringBuilder("UPDATE ");
+        sbr.append(table);
+
+        sbr.append(" SET ");
+        sbr.append(cols.stream().map(k -> getComma() + DbUtil.getColumnName(k) + getComma() + " = ?").collect(Collectors.joining(",")));
+        List<Object> parameters = new ArrayList<>(values);
+        sbr.append(" WHERE 1=1 ");
+        for (Where where : conditions) {
+            if (!DbUtil.isEmptyOrNull(where.key)) {
+                sbr.append(" AND ( ").append(getComma()).append(DbUtil.getColumnName(where.key)).append(getComma()).append(where.op);
+                if (where.op.contains("in") || where.op.contains("not in")) {
+                    sbr.append(" (?) ) ");
+                } else {
+                    sbr.append(" ? ) ");
+                }
+                parameters.add(where.value);
+            } else {
+                if (!DbUtil.isEmptyOrNull(where.sql)) {
+                    sbr.append(" AND (").append(where.sql).append(" ) ");
+                    if (!DbUtil.isEmptyOrNull(where.sqlValues)) {
+                        parameters.addAll(where.sqlValues);
+                    }
+                }
+            }
+        }
+
+        entity.sql = sbr.toString();
+        entity.parameters = parameters.toArray();
+        return entity;
     }
+
+
+    public SQLEntity updateNative(Object o, OBuilder OBuilder, boolean ignoreNull, List<String> includes, List<String> excludes) {
+        this.table = getTableName(o.getClass(), o.getClass().getSimpleName());
+
+//        SQLEntity sqlEntity = new SQLEntity();
+//        List<Object> parameters = new ArrayList<>();
+
+//        StringBuilder sbr = new StringBuilder("UPDATE ");
+//        sbr.append(getTableName(o.getClass(), o.getClass().getSimpleName())).append(" SET ");
+        Set<Field> fields = DbUtil.getEntityFields(o.getClass());
+//        boolean hasUpdateField = false;
+        for (Field field : fields) {
+            if (DbUtil.isUsageField(field)) {
+                DBF dbf = field.getAnnotation(DBF.class);
+                if (null == dbf) {
+                    continue;
+                }
+                String fieldName = field.getName();
+                if (!DbUtil.isEmptyOrNull(excludes)) {
+                    if (excludes.contains(DbUtil.getColumnName(fieldName)) || excludes.contains(fieldName)) {
+                        continue;
+                    }
+                }
+                if (!DbUtil.isEmptyOrNull(includes)) {
+                    if (!includes.contains(fieldName) && !includes.contains(DbUtil.getColumnName(fieldName))) {
+                        continue;
+                    }
+                }
+                if (dbf.canUpdate() && !isImmutableField(fieldName)) {
+                    Type type = field.getGenericType();
+                    Object value = DbUtil.getFieldValue(o, field);
+                    if (ignoreNull) {
+                        if (!DbUtil.isEmptyOrNull(value) && !"0".equals(value.toString())) {
+                            checkFieldValue(field, value, false);
+                            cols.add(fieldName);
+                            values.add(value);
+//                            conditions.add(new Where(fieldName,value));
+//                            sbr.append(getComma()).append(DbUtil.getColumnName(fieldName)).append(getComma()).append("=");
+//                            appendValue(sbr, type, value, parameters);
+//                            hasUpdateField = true;
+                        }
+                    } else {
+                        if (null == value && type == Date.class) {
+                            continue;
+                        }
+                        cols.add(fieldName);
+                        values.add(value);
+//                        sbr.append(getComma()).append(DbUtil.getColumnName(fieldName)).append(getComma()).append("=");
+//                        appendValue(sbr, type, value, parameters);
+//                        hasUpdateField = true;
+                    }
+
+                }
+            }
+        }
+        if (DbUtil.isEmptyOrNull(cols)) {
+            throw new RuntimeException("no field to UPDATE");
+        }
+//        if (sbr.toString().endsWith(",")) {
+//            sbr.deleteCharAt(sbr.length() - 1);
+//        }
+        //where
+        if (null != OBuilder && !DbUtil.isEmptyOrNull(OBuilder.getWheres())) {
+            List<Where> wheres = OBuilder.getWheres();
+            if (!DbUtil.isEmptyOrNull(wheres)) {
+//                sbr.append(" WHERE ");
+                wheres.forEach(wh -> {
+                    if (ignoreNull) {
+                        if (null != wh.value) {
+                            conditions.add(wh);
+//                            sbr.append(getComma()).append(DbUtil.getColumnName(wh.key)).append(getComma()).append(" ").append(wh.op).append(" ");
+//                            appendValue(sbr, wh.value, parameters);
+//                            sbr.append(" AND ");
+                        }
+                    } else {
+                        conditions.add(wh);
+//                        sbr.append(getComma()).append(DbUtil.getColumnName(wh.key)).append(getComma()).append(" ").append(wh.op).append(" ");
+//                        appendValue(sbr, wh.value, parameters);
+//                        sbr.append(" AND ");
+                    }
+                });
+//                sbr.delete(sbr.length() - 5, sbr.length());
+            }
+            //TODO
+        /*    if (SQLExpress.DIALECT_MYSQL == dialect) {
+                //mysql innodb 锁
+                if (OBuilder.forUpdate) {
+                    sbr.append(" FOR UPDATE ");
+                }
+                if (OBuilder.forShare) {
+                    sbr.append(" LOCK IN SHARE MODE");
+                }
+            }*/
+        } else {
+            try {
+                conditions.add(new Where("id", DbUtil.getFieldValue(o, "id")));
+            } catch (Exception e) {
+                throw new IllegalArgumentException("tkf id is not exist!!!");
+            }
+        }
+//        sbr.append(";");
+//        sqlEntity.sql = sbr.toString();
+//        sqlEntity.parameters = parameters.toArray();
+        return toSQL();
+    }
+
+
+    private boolean isImmutableField(String fieldName) {
+        List<String> immutableFields = new ArrayList<>();
+        immutableFields.add("id");
+        immutableFields.add("createat");
+        immutableFields.add("updateat");
+        return immutableFields.contains(fieldName.toLowerCase());
+    }
+
+    public final SQLEntity updateBatch(List<String> fields, List<?> dtoList) {
+        if (DbUtil.isEmptyOrNull(fields)) {
+            throw new IllegalArgumentException("illegal update column, empty column");
+        }
+
+        if (DbUtil.isEmptyOrNull(dtoList)) {
+            throw new IllegalArgumentException("illegal update column, empty data set");
+        }
+
+        SQLEntity entity = new SQLEntity();
+        StringBuilder sbr = new StringBuilder("UPDATE ");
+        String table = getTableName(dtoList.get(0).getClass(), dtoList.get(0).getClass().getSimpleName());
+        sbr.append(table);
+        sbr.append(" SET ");
+        sbr.append(fields.stream().map(k -> getComma() + DbUtil.getColumnName(k) + getComma() + " = ?").collect(Collectors.joining(",")));
+        sbr.append(" WHERE id =  ? ");
+
+        List<Object> pameters = new ArrayList<>();
+        for (Object bean : dtoList) {
+            Object[] objs = new Object[fields.size() + 1];
+            for (int i = 0; i < fields.size(); i++) {
+                objs[i] = DbUtil.getFieldValue(bean, DbUtil.getCamelName(fields.get(i)));
+            }
+            objs[fields.size()] = DbUtil.getFieldValue(bean, "id");
+            pameters.add(objs);
+        }
+
+        entity.sql = sbr.toString();
+        entity.parameters = pameters.toArray();
+        return entity;
+    }
+
 }

Разница между файлами не показана из-за своего большого размера
+ 606 - 249
car-wash-jdbc/src/main/java/com/kym/jdbc/template/JdbcExecute.java


+ 8 - 8
car-wash-jdbc/src/main/java/com/kym/jdbc/template/JdbcHelper.java

@@ -918,24 +918,24 @@ public class JdbcHelper {
             if (query.pageSize > 0) {
                 if (DIALECT_MYSQL == dialect) {
                     sbr.append(" LIMIT ");
-                    if (query.pageNum > 0) {
-                        sbr.append((query.pageNum - 1) * query.pageSize).append(",");
+                    if (query.pageIndex > 0) {
+                        sbr.append((query.pageIndex - 1) * query.pageSize).append(",");
                     }
                     if (query.pageSize > 0) {
                         sbr.append(query.pageSize);
                     }
                 } else if (DIALECT_MSSQL == dialect) {
                     sbr.append(" OFFSET ");
-                    if (query.pageNum > 0) {
-                        sbr.append((query.pageNum - 1) * query.pageSize).append(" ROWS ");
+                    if (query.pageIndex > 0) {
+                        sbr.append((query.pageIndex - 1) * query.pageSize).append(" ROWS ");
                     }
                     if (query.pageSize > 0) {
                         sbr.append(" FETCH NEXT ").append(query.pageSize).append(" ROWS ONLY  ");
                     }
                 } else if (DIALECT_PGSQL == dialect) {
                     sbr.append(" LIMIT ").append(query.pageSize);
-                    if (query.pageNum > 0) {
-                        sbr.append(" OFFSET ").append((query.pageNum - 1) * query.pageSize);
+                    if (query.pageIndex > 0) {
+                        sbr.append(" OFFSET ").append((query.pageIndex - 1) * query.pageSize);
                     }
                 } else if (DIALECT_ORACLE == dialect) {
                     StringBuilder sr = new StringBuilder();
@@ -943,8 +943,8 @@ public class JdbcHelper {
                     if (query.pageSize > 0) {
                         sr.append(" WHERE ROWNUM<=").append(query.pageSize).append(")  o1");
                     }
-                    if (query.pageNum > 0) {
-                        sr.append(" WHERE o1.rowno>").append((query.pageNum - 1) * query.pageSize).append(";");
+                    if (query.pageIndex > 0) {
+                        sr.append(" WHERE o1.rowno>").append((query.pageIndex - 1) * query.pageSize).append(";");
                     }
                     //聚合类使用子查询
                     if (!DbUtil.isEmptyOrNull(aggregate)) {

+ 0 - 15
car-wash-service/src/main/java/com/kym/dao/DbHandler.java

@@ -284,21 +284,6 @@ public class DbHandler extends JdbcExecute {
     }
 
 
-    /**
-     * 批量插入
-     */
-    private void batchInsertExecute(String sql, List<Object[]> ll) {
-        int batch = 1;
-        int batchSize = 256;
-        int totalSize = ll.size();
-        if (totalSize > batchSize) {
-            batch = (int) Math.ceil((double) totalSize / batchSize);
-        }
-        for (int i = 0; i < batch; i++) {
-            List<Object[]> subList = ll.subList(i * batchSize, Math.min(totalSize, ((i + 1) * batchSize)));
-            insertBatch(sql, subList);
-        }
-    }
 
     public void replaceInsert(Object bean) {
         String sql = "replace into t_seed ()";

Некоторые файлы не были показаны из-за большого количества измененных файлов