diff --git a/src/main/java/com/sondertara/joya/annotation/TableAlias.java b/src/main/java/com/sondertara/joya/annotation/TableAlias.java index f22db35..9cb9dc3 100644 --- a/src/main/java/com/sondertara/joya/annotation/TableAlias.java +++ b/src/main/java/com/sondertara/joya/annotation/TableAlias.java @@ -6,21 +6,16 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; - /** * 表别名 * * @author huangxiaohu */ - @Documented @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface TableAlias { - /** - * 表的别名 数据权限使用,应该与模板查询中的别名一致, 默认: a - */ - String value() default "a"; - -} \ No newline at end of file + /** 表的别名 数据权限使用,应该与模板查询中的别名一致, 默认: a */ + String value() default "a"; +} diff --git a/src/main/java/com/sondertara/joya/cache/AliasThreadLocalCache.java b/src/main/java/com/sondertara/joya/cache/AliasThreadLocalCache.java index b49e7bb..e34df37 100644 --- a/src/main/java/com/sondertara/joya/cache/AliasThreadLocalCache.java +++ b/src/main/java/com/sondertara/joya/cache/AliasThreadLocalCache.java @@ -1,6 +1,5 @@ package com.sondertara.joya.cache; - import com.sondertara.common.exception.TaraException; import com.sondertara.common.function.TaraFunction; import com.sondertara.common.lang.Assert; @@ -26,178 +25,194 @@ /** * (non-Javadoc) - *

- * Alias cache based on ThreadLocal - * Save the relationship of query table name and table alias + * + *

Alias cache based on ThreadLocal Save the relationship of query table name and table alias * * @author huangxiaohu */ public final class AliasThreadLocalCache { - /** - * The pattern for get part of method - */ - private static final Pattern GET_PATTERN = Pattern.compile("^get[A-Z].*"); - /** - * The pattern for set part of method - */ - private static final Pattern IS_PATTERN = Pattern.compile("^is[A-Z].*"); - - /** - * (non-Javadoc) - * set table alias - *

- * the table alias will be like t0,t1... - * - * @param aClass the entity class - */ - @SuppressWarnings("unchecked") - public static void generateTableAlias(Class aClass) { - - TableStruct tableStruct = LocalEntityCache.getInstance().get(aClass.getName()).orElseThrow(() -> new TaraException("No entity found with class:{}", aClass.getName())); - LinkedHashMap aliasMap = (LinkedHashMap) ThreadLocalUtil.get(JOYA_SQL); - - TableAlias aliasDTO = new TableAlias(); - aliasDTO.setClassName(aClass.getName()); - aliasDTO.setTableName(tableStruct.getTableName()); - aliasDTO.setAliasName(StringFormatter.format("t{}", aliasMap.size())); - aliasMap.putIfAbsent(aClass.getName(), aliasDTO); - } - - @SuppressWarnings("unchecked") - public static void generateTableAlias(String tableAndAlias) { - Assert.notBlank(tableAndAlias); - String[] strings = tableAndAlias.split(" "); - - LocalEntityCache.getInstance().get(strings[0].toLowerCase()).ifPresent(t -> { - LinkedHashMap aliasMap = (LinkedHashMap) ThreadLocalUtil.get(JOYA_SQL); - - TableAlias aliasDTO = new TableAlias(); - aliasDTO.setClassName(t.getClassName()); - aliasDTO.setTableName(t.getTableName()); - aliasDTO.setAliasName(StringFormatter.format("t{}", aliasMap.size())); - aliasMap.putIfAbsent(t.getClassName(), aliasDTO); - }); - } - - /** - * (non-Javadoc) - * Get the column information - * - * @param taraSqlFn the apply function - * @param generic - * @return Object contain - */ - @SuppressWarnings("unchecked") - public static ColumnAlias getColumn(TaraFunction taraSqlFn) { - try { - Method method = taraSqlFn.getClass().getDeclaredMethod("writeReplace"); - method.setAccessible(Boolean.TRUE); - SerializedLambda serializedLambda = (SerializedLambda) method.invoke(taraSqlFn); - String implClass = serializedLambda.getImplClass(); - String getter = serializedLambda.getImplMethodName(); - - String className = implClass.replace("/", "."); - - Optional optional = LocalEntityCache.getInstance().get(className); - // get the field name - if (GET_PATTERN.matcher(getter).matches()) { - getter = getter.substring(3); - } else if (IS_PATTERN.matcher(getter).matches()) { - getter = getter.substring(2); - } - String finalGetter = getter; - AtomicReference tableName = new AtomicReference<>(); - String columnName = optional.map(tableDTO -> { - Map map = tableDTO.getFields(); - tableName.set(tableDTO.getTableName()); - - String fieldName = StringUtils.lowerFirst(finalGetter); - if (map.containsKey(fieldName)) { - return map.get(fieldName); - } - throw new EntityNotFoundException("No column found by " + finalGetter); - }).orElseThrow(() -> new EntityNotFoundException("no entity found for " + implClass)); - LinkedHashMap aliasMap = (LinkedHashMap) ThreadLocalUtil.get(JOYA_SQL); - TableAlias tableAlias = aliasMap.computeIfAbsent(className, k -> { + /** The pattern for get part of method */ + private static final Pattern GET_PATTERN = Pattern.compile("^get[A-Z].*"); + /** The pattern for set part of method */ + private static final Pattern IS_PATTERN = Pattern.compile("^is[A-Z].*"); + + /** + * (non-Javadoc) set table alias + * + *

the table alias will be like t0,t1... + * + * @param aClass the entity class + */ + @SuppressWarnings("unchecked") + public static void generateTableAlias(Class aClass) { + + TableStruct tableStruct = + LocalEntityCache.getInstance() + .get(aClass.getName()) + .orElseThrow( + () -> new TaraException("No entity found with class:{}", aClass.getName())); + LinkedHashMap aliasMap = + (LinkedHashMap) ThreadLocalUtil.get(JOYA_SQL); + + TableAlias aliasDTO = new TableAlias(); + aliasDTO.setClassName(aClass.getName()); + aliasDTO.setTableName(tableStruct.getTableName()); + aliasDTO.setAliasName(StringFormatter.format("t{}", aliasMap.size())); + aliasMap.putIfAbsent(aClass.getName(), aliasDTO); + } + + @SuppressWarnings("unchecked") + public static void generateTableAlias(String tableAndAlias) { + Assert.notBlank(tableAndAlias); + String[] strings = tableAndAlias.split(" "); + + LocalEntityCache.getInstance() + .get(strings[0].toLowerCase()) + .ifPresent( + t -> { + LinkedHashMap aliasMap = + (LinkedHashMap) ThreadLocalUtil.get(JOYA_SQL); + + TableAlias aliasDTO = new TableAlias(); + aliasDTO.setClassName(t.getClassName()); + aliasDTO.setTableName(t.getTableName()); + aliasDTO.setAliasName(StringFormatter.format("t{}", aliasMap.size())); + aliasMap.putIfAbsent(t.getClassName(), aliasDTO); + }); + } + + /** + * (non-Javadoc) Get the column information + * + * @param taraSqlFn the apply function + * @param generic + * @return Object contain + */ + @SuppressWarnings("unchecked") + public static ColumnAlias getColumn(TaraFunction taraSqlFn) { + try { + Method method = taraSqlFn.getClass().getDeclaredMethod("writeReplace"); + method.setAccessible(Boolean.TRUE); + SerializedLambda serializedLambda = (SerializedLambda) method.invoke(taraSqlFn); + String implClass = serializedLambda.getImplClass(); + String getter = serializedLambda.getImplMethodName(); + + String className = implClass.replace("/", "."); + + Optional optional = LocalEntityCache.getInstance().get(className); + // get the field name + if (GET_PATTERN.matcher(getter).matches()) { + getter = getter.substring(3); + } else if (IS_PATTERN.matcher(getter).matches()) { + getter = getter.substring(2); + } + String finalGetter = getter; + AtomicReference tableName = new AtomicReference<>(); + String columnName = + optional + .map( + tableDTO -> { + Map map = tableDTO.getFields(); + tableName.set(tableDTO.getTableName()); + + String fieldName = StringUtils.lowerFirst(finalGetter); + if (map.containsKey(fieldName)) { + return map.get(fieldName); + } + throw new EntityNotFoundException("No column found by " + finalGetter); + }) + .orElseThrow(() -> new EntityNotFoundException("no entity found for " + implClass)); + LinkedHashMap aliasMap = + (LinkedHashMap) ThreadLocalUtil.get(JOYA_SQL); + TableAlias tableAlias = + aliasMap.computeIfAbsent( + className, + k -> { TableAlias aliasDTO = new TableAlias(); aliasDTO.setTableName(tableName.get()); aliasDTO.setClassName(className); aliasDTO.setAliasName(StringFormatter.format("t{}", aliasMap.size())); return aliasDTO; - }); - ColumnAlias columnAlias = new ColumnAlias(); - columnAlias.setTableName(tableName.get()); - columnAlias.setColumnName(columnName); - columnAlias.setTableAlias(tableAlias.getAliasName()); - columnAlias.setColumnAlias(StringFormatter.format("{}.{}", tableAlias.getAliasName(), columnName)); - return columnAlias; - } catch (ReflectiveOperationException e) { - throw new TaraException(e); - } - + }); + ColumnAlias columnAlias = new ColumnAlias(); + columnAlias.setTableName(tableName.get()); + columnAlias.setColumnName(columnName); + columnAlias.setTableAlias(tableAlias.getAliasName()); + columnAlias.setColumnAlias( + StringFormatter.format("{}.{}", tableAlias.getAliasName(), columnName)); + return columnAlias; + } catch (ReflectiveOperationException e) { + throw new TaraException(e); } - - /** - * (non-Javadoc) - * get all relation tables for the query - * - * @return Object of table - */ - @SuppressWarnings("unchecked") - public static List getTables() { - LinkedHashMap aliasMap = (LinkedHashMap) ThreadLocalUtil.get(JOYA_SQL); - return new ArrayList<>(aliasMap.values()); - + } + + /** + * (non-Javadoc) get all relation tables for the query + * + * @return Object of table + */ + @SuppressWarnings("unchecked") + public static List getTables() { + LinkedHashMap aliasMap = + (LinkedHashMap) ThreadLocalUtil.get(JOYA_SQL); + return new ArrayList<>(aliasMap.values()); + } + + public static TableStruct getTable(String className) { + Optional optional = LocalEntityCache.getInstance().get(className); + return optional.orElseThrow( + () -> new TaraException("No Table found by className:" + className)); + } + + /** + * 获取数据库中的列明名 + * + * @param column 表别名 + * @return 列名 + */ + public static String getColumnName(String column) { + + if (null == column) { + return null; } - - public static TableStruct getTable(String className) { - Optional optional = LocalEntityCache.getInstance().get(className); - return optional.orElseThrow(() -> new TaraException("No Table found by className:" + className)); + int index = column.indexOf("."); + if (index < 0) { + throw new TaraException("The column is incorrect,it should like 't0.userName.'"); } - - - /** - * 获取数据库中的列明名 - * - * @param column 表别名 - * @return 列名 - */ - public static String getColumnName(String column) { - - if (null == column) { - return null; - } - int index = column.indexOf("."); - if (index < 0) { - throw new TaraException("The column is incorrect,it should like 't0.userName.'"); - } - String tableAlias = column.substring(0, index); - String fieldName = column.substring(index + 1); - String s = null; - List tables = getTables(); - for (TableAlias table : tables) { - if (tableAlias.equals(table.getAliasName())) { - String className = table.getClassName(); - s = LocalEntityCache.getInstance().get(className).map(t -> { - - Map fields = t.getFields(); - // if the column is entity field - if (fields.containsKey(StringUtils.toCamelCase(fieldName))) { + String tableAlias = column.substring(0, index); + String fieldName = column.substring(index + 1); + String s = null; + List tables = getTables(); + for (TableAlias table : tables) { + if (tableAlias.equals(table.getAliasName())) { + String className = table.getClassName(); + s = + LocalEntityCache.getInstance() + .get(className) + .map( + t -> { + Map fields = t.getFields(); + // if the column is entity field + if (fields.containsKey(StringUtils.toCamelCase(fieldName))) { return fields.get(StringUtils.toCamelCase(fieldName)); - } else { + } else { // if the column is table column for (String value : fields.values()) { - if (value.equalsIgnoreCase(StringUtils.toUnderlineCase(fieldName))) { - return value; - } + if (value.equalsIgnoreCase(StringUtils.toUnderlineCase(fieldName))) { + return value; + } } - } - throw new TaraException("No column found for table [{}] by name [{}]", table.getTableName(), fieldName); - }).orElseThrow(() -> new TaraException("No table found by className [{}]", className)); - } - } - return StringFormatter.format("{}.{}", tableAlias, s); + } + throw new TaraException( + "No column found for table [{}] by name [{}]", + table.getTableName(), + fieldName); + }) + .orElseThrow( + () -> new TaraException("No table found by className [{}]", className)); + } } - + return StringFormatter.format("{}.{}", tableAlias, s); + } } diff --git a/src/main/java/com/sondertara/joya/cache/LocalEntityCache.java b/src/main/java/com/sondertara/joya/cache/LocalEntityCache.java index 34c07cd..7605098 100644 --- a/src/main/java/com/sondertara/joya/cache/LocalEntityCache.java +++ b/src/main/java/com/sondertara/joya/cache/LocalEntityCache.java @@ -11,80 +11,75 @@ import java.util.List; import java.util.Optional; - /** * local cache for five min * * @author huangxiaohu */ -public class LocalEntityCache extends GuavaAbstractLoadingCache implements ILocalCache { +public class LocalEntityCache extends GuavaAbstractLoadingCache + implements ILocalCache { - private static final Logger log = LoggerFactory.getLogger(LocalEntityCache.class); + private static final Logger log = LoggerFactory.getLogger(LocalEntityCache.class); - private static volatile LocalEntityCache cache = null; + private static volatile LocalEntityCache cache = null; - private LocalEntityCache() { - setMaximumSize(1000); - setExpireAfterWriteDuration(60 * 5); - } + private LocalEntityCache() { + setMaximumSize(1000); + setExpireAfterWriteDuration(60 * 5); + } - private AbstractTableResult tableResult; + private AbstractTableResult tableResult; - public synchronized static LocalEntityCache getInstance() { + public static synchronized LocalEntityCache getInstance() { + if (null == cache) { + synchronized (LocalEntityCache.class) { if (null == cache) { - synchronized (LocalEntityCache.class) { - if (null == cache) { - cache = new LocalEntityCache(); - cache.setTableResult(new EntityManagerTableResultAdapter()); - } - } - } - return cache; - } - - public void setTableResult(AbstractTableResult tableResult) { - this.tableResult = tableResult; - } - - @Override - protected TableStruct fetchData(String key) { - - List list = tableResult.load(); - for (TableStruct tableStruct : list) { - if (tableStruct.getTableName().equalsIgnoreCase(key)) { - put(tableStruct.getClassName(), tableStruct); - return tableStruct; - } else if (tableStruct.getClassName().equalsIgnoreCase(key)) { - put(tableStruct.getTableName(), tableStruct); - return tableStruct; - } - } - log.warn("no data to load by key=[{}]", key); - return null; - - - } - - @Override - public Optional get(String key) { - TableStruct value = null; - try { - value = getValue(key); - } catch (Exception e) { - log.error("key={}获取数据异常", key, e); + cache = new LocalEntityCache(); + cache.setTableResult(new EntityManagerTableResultAdapter()); } - return Optional.ofNullable(value); + } } - - @Override - public void remove(String key) { - invalidate(key); - + return cache; + } + + public void setTableResult(AbstractTableResult tableResult) { + this.tableResult = tableResult; + } + + @Override + protected TableStruct fetchData(String key) { + + List list = tableResult.load(); + for (TableStruct tableStruct : list) { + if (tableStruct.getTableName().equalsIgnoreCase(key)) { + put(tableStruct.getClassName(), tableStruct); + return tableStruct; + } else if (tableStruct.getClassName().equalsIgnoreCase(key)) { + put(tableStruct.getTableName(), tableStruct); + return tableStruct; + } } - - - public void removeAll() { - invalidateAll(); - + log.warn("no data to load by key=[{}]", key); + return null; + } + + @Override + public Optional get(String key) { + TableStruct value = null; + try { + value = getValue(key); + } catch (Exception e) { + log.error("key={}获取数据异常", key, e); } -} \ No newline at end of file + return Optional.ofNullable(value); + } + + @Override + public void remove(String key) { + invalidate(key); + } + + public void removeAll() { + invalidateAll(); + } +} diff --git a/src/main/java/com/sondertara/joya/cache/TableClassCache.java b/src/main/java/com/sondertara/joya/cache/TableClassCache.java index f37ff6a..7823195 100644 --- a/src/main/java/com/sondertara/joya/cache/TableClassCache.java +++ b/src/main/java/com/sondertara/joya/cache/TableClassCache.java @@ -26,212 +26,211 @@ /** * @author skydu */ -public class TableClassCache extends GuavaAbstractLoadingCache, Map> implements ILocalCache, Map> { +public class TableClassCache extends GuavaAbstractLoadingCache, Map> + implements ILocalCache, Map> { - private static volatile TableClassCache cache = null; - - private TableClassCache() { - setMaximumSize(1000); - setExpireAfterWriteDuration(60 * 60); - } + private static volatile TableClassCache cache = null; + private TableClassCache() { + setMaximumSize(1000); + setExpireAfterWriteDuration(60 * 60); + } - public synchronized static TableClassCache getInstance() { + public static synchronized TableClassCache getInstance() { + if (null == cache) { + synchronized (TableClassCache.class) { if (null == cache) { - synchronized (TableClassCache.class) { - if (null == cache) { - cache = new TableClassCache(); - } - } + cache = new TableClassCache(); } - return cache; + } } - - /** - * @return get current classloader - */ - public static ClassLoader getDefaultClassLoader() { - ClassLoader cl = null; + return cache; + } + + /** + * @return get current classloader + */ + public static ClassLoader getDefaultClassLoader() { + ClassLoader cl = null; + try { + cl = Thread.currentThread().getContextClassLoader(); + } catch (Throwable ex) { + // Cannot access thread context ClassLoader - falling back... + } + if (cl == null) { + // No thread context class loader -> use class loader of this class. + cl = TableClassCache.class.getClassLoader(); + if (cl == null) { + // getClassLoader() returning null indicates the bootstrap ClassLoader try { - cl = Thread.currentThread().getContextClassLoader(); + cl = ClassLoader.getSystemClassLoader(); } catch (Throwable ex) { - // Cannot access thread context ClassLoader - falling back... + // Cannot access system ClassLoader - oh well, maybe the caller can live with + // null... } - if (cl == null) { - // No thread context class loader -> use class loader of this class. - cl = TableClassCache.class.getClassLoader(); - if (cl == null) { - // getClassLoader() returning null indicates the bootstrap ClassLoader - try { - cl = ClassLoader.getSystemClassLoader(); - } catch (Throwable ex) { - // Cannot access system ClassLoader - oh well, maybe the caller can live with - // null... - } - } - } - return cl; + } } - - /** - * 获取类的所有字段(包括父类的) - * - * @param clazz class - * @return field - */ - public static Map getAllFields(Class clazz) { - Map fields = Maps.newLinkedHashMap(); - Set filedNames = new HashSet<>(); - for (Class c = clazz; c != Object.class; c = c.getSuperclass()) { - try { - Field[] list = c.getDeclaredFields(); - for (Field field : list) { - String name = field.getName(); - if (filedNames.contains(name)) { - continue; - } - filedNames.add(field.getName()); - fields.put(field.getName(), field); - } - } catch (Exception e) { - throw new TaraException(e); - } + return cl; + } + + /** + * 获取类的所有字段(包括父类的) + * + * @param clazz class + * @return field + */ + public static Map getAllFields(Class clazz) { + Map fields = Maps.newLinkedHashMap(); + Set filedNames = new HashSet<>(); + for (Class c = clazz; c != Object.class; c = c.getSuperclass()) { + try { + Field[] list = c.getDeclaredFields(); + for (Field field : list) { + String name = field.getName(); + if (filedNames.contains(name)) { + continue; + } + filedNames.add(field.getName()); + fields.put(field.getName(), field); } - return fields; + } catch (Exception e) { + throw new TaraException(e); + } } - - - /** - * 获取一个实体类对应数据库字段 - * - * @param bean java pojo - * @param the class type of bean - * @return the table data - */ - public TableEntity getTable(T bean, boolean readData) { - Map filedNames = new LinkedHashMap<>(); - Map relation = Maps.newHashMap(); - Class clazz = bean.getClass(); - Table table = clazz.getAnnotation(Table.class); - String tableName = null; - if (null != table) { - tableName = table.name(); - } else { - Entity entity = clazz.getAnnotation(Entity.class); - if (null != entity) { - tableName = entity.name(); - } - } - if (null == tableName) { - throw new TaraException("No [@Table] or [@Entity] annotation found for class->" + clazz); - } - TableEntity tableDTO = new TableEntity(); - tableDTO.setTableName(tableName); - Optional> optional = get(clazz); - return optional.map(fields -> { - for (Field field : fields.values()) { + return fields; + } + + /** + * 获取一个实体类对应数据库字段 + * + * @param bean java pojo + * @param the class type of bean + * @return the table data + */ + public TableEntity getTable(T bean, boolean readData) { + Map filedNames = new LinkedHashMap<>(); + Map relation = Maps.newHashMap(); + Class clazz = bean.getClass(); + Table table = clazz.getAnnotation(Table.class); + String tableName = null; + if (null != table) { + tableName = table.name(); + } else { + Entity entity = clazz.getAnnotation(Entity.class); + if (null != entity) { + tableName = entity.name(); + } + } + if (null == tableName) { + throw new TaraException("No [@Table] or [@Entity] annotation found for class->" + clazz); + } + TableEntity tableDTO = new TableEntity(); + tableDTO.setTableName(tableName); + Optional> optional = get(clazz); + return optional + .map( + fields -> { + for (Field field : fields.values()) { if (Modifier.isStatic(field.getModifiers())) { - continue; + continue; } - if (field.isAnnotationPresent(Transient.class) || field.isAnnotationPresent(org.springframework.data.annotation.Transient.class)) { - continue; + if (field.isAnnotationPresent(Transient.class) + || field.isAnnotationPresent( + org.springframework.data.annotation.Transient.class)) { + continue; } String name = field.getName(); name = StringUtils.toUnderlineCase(name); Column column = field.getAnnotation(Column.class); if (null != column) { - name = column.name(); + name = column.name(); } Id id = field.getAnnotation(Id.class); if (null != id) { - tableDTO.setPrimaryKey(name); - tableDTO.setPrimaryKeyType(field.getType()); + tableDTO.setPrimaryKey(name); + tableDTO.setPrimaryKeyType(field.getType()); } if (filedNames.containsKey(name)) { - continue; + continue; } if (readData) { - try { - Object o; - if (field.isAccessible()) { - o = field.get(bean); - } else { - field.setAccessible(true); - o = field.get(bean); - field.setAccessible(false); - } - filedNames.put(name, o); - } catch (Exception e) { - e.printStackTrace(); + try { + Object o; + if (field.isAccessible()) { + o = field.get(bean); + } else { + field.setAccessible(true); + o = field.get(bean); + field.setAccessible(false); } + filedNames.put(name, o); + } catch (Exception e) { + e.printStackTrace(); + } } relation.put(name, field.getName()); - - } - tableDTO.setData(filedNames); - tableDTO.setRelation(relation); - return tableDTO; - }).orElseThrow(() -> new TaraException("Get Class definition error")); - + } + tableDTO.setData(filedNames); + tableDTO.setRelation(relation); + return tableDTO; + }) + .orElseThrow(() -> new TaraException("Get Class definition error")); + } + + /** + * @param clazz + * @return the super class + */ + public static Class getSuperClassGenricType(Class clazz) { + Type genType = clazz.getGenericSuperclass(); + if (!(genType instanceof ParameterizedType)) { + if (genType instanceof Class) { + return getSuperClassGenricType((Class) genType); + } + return Object.class; } - - /** - * @param clazz - * @return the super class - */ - public static Class getSuperClassGenricType(Class clazz) { - Type genType = clazz.getGenericSuperclass(); - if (!(genType instanceof ParameterizedType)) { - if (genType instanceof Class) { - return getSuperClassGenricType((Class) genType); - } - return Object.class; - } - Type[] params = ((ParameterizedType) genType).getActualTypeArguments(); - if (params.length == 0) { - return Object.class; - } - return (Class) params[0]; + Type[] params = ((ParameterizedType) genType).getActualTypeArguments(); + if (params.length == 0) { + return Object.class; } - - - /** - * @param clazz the class - * @param fieldName field name - * @return the current Field - */ - public static Field getField(Class clazz, String fieldName) { - Map map = getAllFields(clazz); - return map.get(fieldName); + return (Class) params[0]; + } + + /** + * @param clazz the class + * @param fieldName field name + * @return the current Field + */ + public static Field getField(Class clazz, String fieldName) { + Map map = getAllFields(clazz); + return map.get(fieldName); + } + + public static Class classForName(String name) throws ClassNotFoundException { + try { + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + if (classLoader != null) { + return classLoader.loadClass(name); + } + } catch (Throwable ignore) { } - - public static Class classForName(String name) throws ClassNotFoundException { - try { - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - if (classLoader != null) { - return classLoader.loadClass(name); - } - } catch (Throwable ignore) { - } - return Class.forName(name); + return Class.forName(name); + } + + @Override + protected Map fetchData(Class key) { + return getAllFields(key); + } + + @Override + public Optional> get(Class key) { + try { + return Optional.ofNullable(getValue(key)); + } catch (ExecutionException e) { + throw new TaraException(e); } + } - @Override - protected Map fetchData(Class key) { - return getAllFields(key); - } - - @Override - public Optional> get(Class key) { - try { - return Optional.ofNullable(getValue(key)); - } catch (ExecutionException e) { - throw new TaraException(e); - } - } - - @Override - public void remove(Class key) { - - } + @Override + public void remove(Class key) {} } diff --git a/src/main/java/com/sondertara/joya/core/builder/ExtPartBuilder.java b/src/main/java/com/sondertara/joya/core/builder/ExtPartBuilder.java index f039cad..97069d0 100644 --- a/src/main/java/com/sondertara/joya/core/builder/ExtPartBuilder.java +++ b/src/main/java/com/sondertara/joya/core/builder/ExtPartBuilder.java @@ -11,41 +11,41 @@ */ public interface ExtPartBuilder extends SetupBuilder { - /** - * group by - * - * @param groupBySegment param - * @return the builder - */ - ExtPartBuilder groupBy(String groupBySegment); + /** + * group by + * + * @param groupBySegment param + * @return the builder + */ + ExtPartBuilder groupBy(String groupBySegment); - /** - * having - *

- * example:nativeSql.having(h -> h.eq().ne().in()) - * - * @param func the function - * @return the builder - */ - ExtPartBuilder having(UnaryOperator func); + /** + * having + * + *

example:nativeSql.having(h -> h.eq().ne().in()) + * + * @param func the function + * @return the builder + */ + ExtPartBuilder having(UnaryOperator func); - /** - * order by with function - *

- * example: nativeSql.orderBy("su.age asc") - * - * @param fn the column function - * @param orderBy the order type - * @param the type of table class - * @return the builder - */ - ExtPartBuilder orderBy(TaraFunction fn, OrderParam.OrderBy orderBy); + /** + * order by with function + * + *

example: nativeSql.orderBy("su.age asc") + * + * @param fn the column function + * @param orderBy the order type + * @param the type of table class + * @return the builder + */ + ExtPartBuilder orderBy(TaraFunction fn, OrderParam.OrderBy orderBy); - /** - * order by with string - * - * @param orderBySegment order by params - * @return the builder - */ - ExtPartBuilder orderBy(String... orderBySegment); + /** + * order by with string + * + * @param orderBySegment order by params + * @return the builder + */ + ExtPartBuilder orderBy(String... orderBySegment); } diff --git a/src/main/java/com/sondertara/joya/core/builder/FromBuilder.java b/src/main/java/com/sondertara/joya/core/builder/FromBuilder.java index bfe3f3b..ea1378b 100644 --- a/src/main/java/com/sondertara/joya/core/builder/FromBuilder.java +++ b/src/main/java/com/sondertara/joya/core/builder/FromBuilder.java @@ -9,34 +9,33 @@ */ public interface FromBuilder { - /** - * sql from part with string - * - * @param tableAndJoinTable the sql from segment - * @return the next builder - */ - WhereBuilder from(String... tableAndJoinTable); + /** + * sql from part with string + * + * @param tableAndJoinTable the sql from segment + * @return the next builder + */ + WhereBuilder from(String... tableAndJoinTable); - /** - * the table class - *

- * when use it the table alias will set to default like t0,t1... - * 根据class获取表,别名为表的顺序t0,t1,t2,t2 - * - * @param clazz form entity class - * @return query - */ - WhereBuilder from(Class... clazz); + /** + * the table class + * + *

when use it the table alias will set to default like t0,t1... 根据class获取表,别名为表的顺序t0,t1,t2,t2 + * + * @param clazz form entity class + * @return query + */ + WhereBuilder from(Class... clazz); - /** - * the table class with join params - *

- * the limit is only support join tree table,if there is complicated sql query just use the native sql - * when use it the table alias will set to default like t0,t1... - * 根据class获取表,别名为表的顺序t0,t1,t2,t2 - * - * @param func join param - * @return query - */ - WhereBuilder from(UnaryOperator func); -} \ No newline at end of file + /** + * the table class with join params + * + *

the limit is only support join tree table,if there is complicated sql query just use the + * native sql when use it the table alias will set to default like t0,t1... + * 根据class获取表,别名为表的顺序t0,t1,t2,t2 + * + * @param func join param + * @return query + */ + WhereBuilder from(UnaryOperator func); +} diff --git a/src/main/java/com/sondertara/joya/core/builder/SelectBuilder.java b/src/main/java/com/sondertara/joya/core/builder/SelectBuilder.java index cdf79d6..f09cbdf 100644 --- a/src/main/java/com/sondertara/joya/core/builder/SelectBuilder.java +++ b/src/main/java/com/sondertara/joya/core/builder/SelectBuilder.java @@ -6,123 +6,174 @@ import java.util.function.UnaryOperator; /** - * (non-javadoc) - * the select builder + * (non-javadoc) the select builder * * @author huangxiaohu */ public interface SelectBuilder { - /** - * sql select part - *

- * example: [t0.user_name] or [t0.usr_name AS userName] - * select 要查询的列 格式为[t0.user_name] 或者[t0.usr_name AS userName] - * - * @param columns the query columns - * @return the next builder - */ - FromBuilder select(String... columns); - - /** - * sql select part - *

- * this function will query all columns (select *),you can use {@link #wrapColumn(String...)} together to assign alias - *

- * 查询表的全部列,对于联表查询 如果字段名字有重复,只保留前面一个字段,可以配置specificS来指定字段别名 - * - * @return the next builder - */ - FromBuilder select(); - - /** - * the special query column like as alias. - *

- * 特殊select 字段 搭配select(),指定字段的别名 - * - * @param selectFields the special column,usually is the column alias - * @return this builder - */ - SelectBuilder wrapColumn(String... selectFields); - - /** - * select single column - * 选择一个字段 - * - * @param f1 column - * @param entity - * @return the next builder - */ - FromBuilder select(TaraFunction f1); - - /** - * select two column - * - * @param f1 column1 - * @param f2 column2 - * @param entity1 - * @param entity2 - * @return query - */ - FromBuilder select(TaraFunction f1, TaraFunction f2); - - /** - * (non-javadoc) - */ - FromBuilder select(TaraFunction f1, TaraFunction f2, TaraFunction f3); - - /** - * (non-javadoc) - */ - FromBuilder select(TaraFunction f1, TaraFunction f2, TaraFunction f3, TaraFunction f4); - - /** - * (non-javadoc) - */ - FromBuilder select(TaraFunction f1, TaraFunction f2, TaraFunction f3, TaraFunction f4, TaraFunction f5); - - /** - * (non-javadoc) - */ - FromBuilder select(TaraFunction f1, TaraFunction f2, TaraFunction f3, TaraFunction f4, TaraFunction f5, TaraFunction f6); - - /** - * (non-javadoc) - */ - FromBuilder select(TaraFunction f1, TaraFunction f2, TaraFunction f3, TaraFunction f4, TaraFunction f5, TaraFunction f6, TaraFunction f7); - - /** - * (non-javadoc) - */ - FromBuilder select(TaraFunction f1, TaraFunction f2, TaraFunction f3, TaraFunction f4, TaraFunction f5, TaraFunction f6, TaraFunction f7, TaraFunction f8); - - /** - * (non-javadoc) - */ - FromBuilder select(TaraFunction f1, TaraFunction f2, TaraFunction f3, TaraFunction f4, TaraFunction f5, TaraFunction f6, TaraFunction f7, TaraFunction f8, TaraFunction f9); - - /** - * (non-javadoc) - */ - FromBuilder select(TaraFunction f1, TaraFunction f2, TaraFunction f3, TaraFunction f4, TaraFunction f5, TaraFunction f6, TaraFunction f7, TaraFunction f8, TaraFunction f9, TaraFunction f10); - - /** - * (non-javadoc) - */ - FromBuilder select(TaraFunction f1, TaraFunction f2, TaraFunction f3, TaraFunction f4, TaraFunction f5, TaraFunction f6, TaraFunction f7, TaraFunction f8, TaraFunction f9, TaraFunction f10, TaraFunction f11); - - /** - * (non-javadoc) - */ - FromBuilder select(TaraFunction f1, TaraFunction f2, TaraFunction f3, TaraFunction f4, TaraFunction f5, TaraFunction f6, TaraFunction f7, TaraFunction f8, TaraFunction f9, TaraFunction f10, TaraFunction f11, TaraFunction f12); - - /** - * the lambda select, use {@link #wrapColumn(String...)} (String...)} the resolve alias - * lambda select 同样冲突字段需要调用specificS() - * - * @param func select field - * @return query - */ - FromBuilder select(UnaryOperator func); - -} \ No newline at end of file + /** + * sql select part + * + *

example: [t0.user_name] or [t0.usr_name AS userName] select 要查询的列 格式为[t0.user_name] + * 或者[t0.usr_name AS userName] + * + * @param columns the query columns + * @return the next builder + */ + FromBuilder select(String... columns); + + /** + * sql select part + * + *

this function will query all columns (select *),you can use {@link #wrapColumn(String...)} + * together to assign alias + * + *

查询表的全部列,对于联表查询 如果字段名字有重复,只保留前面一个字段,可以配置specificS来指定字段别名 + * + * @return the next builder + */ + FromBuilder select(); + + /** + * the special query column like as alias. + * + *

特殊select 字段 搭配select(),指定字段的别名 + * + * @param selectFields the special column,usually is the column alias + * @return this builder + */ + SelectBuilder wrapColumn(String... selectFields); + + /** + * select single column 选择一个字段 + * + * @param f1 column + * @param entity + * @return the next builder + */ + FromBuilder select(TaraFunction f1); + + /** + * select two column + * + * @param f1 column1 + * @param f2 column2 + * @param entity1 + * @param entity2 + * @return query + */ + FromBuilder select(TaraFunction f1, TaraFunction f2); + + /** (non-javadoc) */ + FromBuilder select( + TaraFunction f1, TaraFunction f2, TaraFunction f3); + + /** (non-javadoc) */ + FromBuilder select( + TaraFunction f1, + TaraFunction f2, + TaraFunction f3, + TaraFunction f4); + + /** (non-javadoc) */ + FromBuilder select( + TaraFunction f1, + TaraFunction f2, + TaraFunction f3, + TaraFunction f4, + TaraFunction f5); + + /** (non-javadoc) */ + FromBuilder select( + TaraFunction f1, + TaraFunction f2, + TaraFunction f3, + TaraFunction f4, + TaraFunction f5, + TaraFunction f6); + + /** (non-javadoc) */ + FromBuilder select( + TaraFunction f1, + TaraFunction f2, + TaraFunction f3, + TaraFunction f4, + TaraFunction f5, + TaraFunction f6, + TaraFunction f7); + + /** (non-javadoc) */ + FromBuilder select( + TaraFunction f1, + TaraFunction f2, + TaraFunction f3, + TaraFunction f4, + TaraFunction f5, + TaraFunction f6, + TaraFunction f7, + TaraFunction f8); + + /** (non-javadoc) */ + FromBuilder select( + TaraFunction f1, + TaraFunction f2, + TaraFunction f3, + TaraFunction f4, + TaraFunction f5, + TaraFunction f6, + TaraFunction f7, + TaraFunction f8, + TaraFunction f9); + + /** (non-javadoc) */ + FromBuilder select( + TaraFunction f1, + TaraFunction f2, + TaraFunction f3, + TaraFunction f4, + TaraFunction f5, + TaraFunction f6, + TaraFunction f7, + TaraFunction f8, + TaraFunction f9, + TaraFunction f10); + + /** (non-javadoc) */ + FromBuilder select( + TaraFunction f1, + TaraFunction f2, + TaraFunction f3, + TaraFunction f4, + TaraFunction f5, + TaraFunction f6, + TaraFunction f7, + TaraFunction f8, + TaraFunction f9, + TaraFunction f10, + TaraFunction f11); + + /** (non-javadoc) */ + FromBuilder select( + TaraFunction f1, + TaraFunction f2, + TaraFunction f3, + TaraFunction f4, + TaraFunction f5, + TaraFunction f6, + TaraFunction f7, + TaraFunction f8, + TaraFunction f9, + TaraFunction f10, + TaraFunction f11, + TaraFunction f12); + + /** + * the lambda select, use {@link #wrapColumn(String...)} (String...)} the resolve alias lambda + * select 同样冲突字段需要调用specificS() + * + * @param func select field + * @return query + */ + FromBuilder select(UnaryOperator func); +} diff --git a/src/main/java/com/sondertara/joya/core/builder/SetupBuilder.java b/src/main/java/com/sondertara/joya/core/builder/SetupBuilder.java index e675a9e..ebd34cc 100644 --- a/src/main/java/com/sondertara/joya/core/builder/SetupBuilder.java +++ b/src/main/java/com/sondertara/joya/core/builder/SetupBuilder.java @@ -3,17 +3,15 @@ import com.sondertara.joya.core.query.NativeSqlQuery; /** - * (non-javadoc) - * the start builder + * (non-javadoc) the start builder * * @author huangxiaohu */ public interface SetupBuilder { - /** - * builder the NativeSqlQuery - * 构造 NativeSqlQuery - * - * @return sql - */ - NativeSqlQuery build(); + /** + * builder the NativeSqlQuery 构造 NativeSqlQuery + * + * @return sql + */ + NativeSqlQuery build(); } diff --git a/src/main/java/com/sondertara/joya/core/builder/WhereBuilder.java b/src/main/java/com/sondertara/joya/core/builder/WhereBuilder.java index 3cb373e..0b6311a 100644 --- a/src/main/java/com/sondertara/joya/core/builder/WhereBuilder.java +++ b/src/main/java/com/sondertara/joya/core/builder/WhereBuilder.java @@ -9,26 +9,23 @@ */ public interface WhereBuilder extends ExtPartBuilder { - - /** - * lambda where - *

- * example :nativeSql.where(w -> w.eq().ne().in()) - * - * @param func the function - * @return the next builder - */ - ExtPartBuilder where(UnaryOperator func); - - - /** - * where part with appoint the condition link type,default is #AND - * 使用方式: nativeSql.where(w -> w.eq().ne().in()) - * - * @param func 条件 - * @param linkOr 是否为or查询 默认为and - * @return the next builder - */ - ExtPartBuilder where(UnaryOperator func, boolean linkOr); - -} \ No newline at end of file + /** + * lambda where + * + *

example :nativeSql.where(w -> w.eq().ne().in()) + * + * @param func the function + * @return the next builder + */ + ExtPartBuilder where(UnaryOperator func); + + /** + * where part with appoint the condition link type,default is #AND 使用方式: nativeSql.where(w -> + * w.eq().ne().in()) + * + * @param func 条件 + * @param linkOr 是否为or查询 默认为and + * @return the next builder + */ + ExtPartBuilder where(UnaryOperator func, boolean linkOr); +} diff --git a/src/main/java/com/sondertara/joya/core/constant/JoyaConst.java b/src/main/java/com/sondertara/joya/core/constant/JoyaConst.java index 0aeabad..d484683 100644 --- a/src/main/java/com/sondertara/joya/core/constant/JoyaConst.java +++ b/src/main/java/com/sondertara/joya/core/constant/JoyaConst.java @@ -8,33 +8,21 @@ * @since 1.0.1 */ public class JoyaConst { - /** - * the local cache key - */ - public static final String JOYA_SQL = "JOYA_SQL"; - /** - * column alias split - */ - public static final String ALIAS_SPLIT = "."; - - /** - * maximum join part - */ - public static final int MAX_JOIN_COUNT = 4; - /** - * maximum join table - */ - public static final int MAX_JOIN_TABLE = 3; - /** - * two count - */ - public static final int TWO_QUERY_COUNT = 2; - - - public static class Sql { - public static final String ORACLE_GET_CURRENT_SCHEMA = "SELECT sys_context('userenv','current_schema') FROM DUAL"; - public static final String ORACLE_SET_CURRENT_SCHEMA = "alter session set current_schema = ?"; - } + /** the local cache key */ + public static final String JOYA_SQL = "JOYA_SQL"; + /** column alias split */ + public static final String ALIAS_SPLIT = "."; + /** maximum join part */ + public static final int MAX_JOIN_COUNT = 4; + /** maximum join table */ + public static final int MAX_JOIN_TABLE = 3; + /** two count */ + public static final int TWO_QUERY_COUNT = 2; + public static class Sql { + public static final String ORACLE_GET_CURRENT_SCHEMA = + "SELECT sys_context('userenv','current_schema') FROM DUAL"; + public static final String ORACLE_SET_CURRENT_SCHEMA = "alter session set current_schema = ?"; + } } diff --git a/src/main/java/com/sondertara/joya/core/data/AbstractTableResult.java b/src/main/java/com/sondertara/joya/core/data/AbstractTableResult.java index 83f5ac2..7a5fa83 100644 --- a/src/main/java/com/sondertara/joya/core/data/AbstractTableResult.java +++ b/src/main/java/com/sondertara/joya/core/data/AbstractTableResult.java @@ -8,10 +8,10 @@ * @author huangxiaohu */ public abstract class AbstractTableResult { - /** - * Load the table information and the entity class of the associated control. - * - * @return the list of table - */ - public abstract List load(); + /** + * Load the table information and the entity class of the associated control. + * + * @return the list of table + */ + public abstract List load(); } diff --git a/src/main/java/com/sondertara/joya/core/data/EntityManagerTableResultAdapter.java b/src/main/java/com/sondertara/joya/core/data/EntityManagerTableResultAdapter.java index 799647e..8058947 100644 --- a/src/main/java/com/sondertara/joya/core/data/EntityManagerTableResultAdapter.java +++ b/src/main/java/com/sondertara/joya/core/data/EntityManagerTableResultAdapter.java @@ -21,40 +21,53 @@ import java.util.Optional; /** - * Get the tables with EntityManager - * you can implement your own adapter,and customize it by use {@link LocalEntityCache#setTableResult(AbstractTableResult)} + * Get the tables with EntityManager you can implement your own adapter,and customize it by use + * {@link LocalEntityCache#setTableResult(AbstractTableResult)} * * @author huangxiaohu */ public class EntityManagerTableResultAdapter extends AbstractTableResult { - @Override - public List load() { - List result = new ArrayList<>(); - EntityManager entityManager = JoyaSpringContext.getBean(EntityManager.class); - Metamodel metamodel = entityManager.getEntityManagerFactory().getMetamodel(); - for (EntityType entity : metamodel.getEntities()) { - Class aClass = entity.getJavaType(); - Table annotation = aClass.getAnnotation(Table.class); - String tableName = Optional.of(annotation).map(Table::name).orElseThrow(() -> new EntityNotFoundException(StringFormatter.format("no entity found for class [{}]", aClass.getName()))); - Map fieldNames = new LinkedHashMap<>(); - Field[] fields = aClass.getDeclaredFields(); - for (Field field : fields) { - if (Modifier.isStatic(field.getModifiers())) { - continue; - } - field.setAccessible(true); - Column fieldAnnotation = field.getAnnotation(Column.class); - String columnName = Optional.ofNullable(fieldAnnotation).map(f -> StringUtils.isBlank(f.name()) ? StringUtils.toUnderlineCase(field.getName()) : StringUtils.toLowerCase(f.name())).orElse(StringUtils.toUnderlineCase(field.getName())); - fieldNames.put(field.getName(), columnName); - field.setAccessible(false); - } - TableStruct tableStruct = new TableStruct(); - tableStruct.setClassName(aClass.getName()); - tableStruct.setTableName(tableName); - tableStruct.setFields(fieldNames); - result.add(tableStruct); + @Override + public List load() { + List result = new ArrayList<>(); + EntityManager entityManager = JoyaSpringContext.getBean(EntityManager.class); + Metamodel metamodel = entityManager.getEntityManagerFactory().getMetamodel(); + for (EntityType entity : metamodel.getEntities()) { + Class aClass = entity.getJavaType(); + Table annotation = aClass.getAnnotation(Table.class); + String tableName = + Optional.of(annotation) + .map(Table::name) + .orElseThrow( + () -> + new EntityNotFoundException( + StringFormatter.format( + "no entity found for class [{}]", aClass.getName()))); + Map fieldNames = new LinkedHashMap<>(); + Field[] fields = aClass.getDeclaredFields(); + for (Field field : fields) { + if (Modifier.isStatic(field.getModifiers())) { + continue; } - return result; + field.setAccessible(true); + Column fieldAnnotation = field.getAnnotation(Column.class); + String columnName = + Optional.ofNullable(fieldAnnotation) + .map( + f -> + StringUtils.isBlank(f.name()) + ? StringUtils.toUnderlineCase(field.getName()) + : StringUtils.toLowerCase(f.name())) + .orElse(StringUtils.toUnderlineCase(field.getName())); + fieldNames.put(field.getName(), columnName); + field.setAccessible(false); + } + TableStruct tableStruct = new TableStruct(); + tableStruct.setClassName(aClass.getName()); + tableStruct.setTableName(tableName); + tableStruct.setFields(fieldNames); + result.add(tableStruct); } - + return result; + } } diff --git a/src/main/java/com/sondertara/joya/core/jdbc/ConnectionCallback.java b/src/main/java/com/sondertara/joya/core/jdbc/ConnectionCallback.java index 98de782..037cde2 100644 --- a/src/main/java/com/sondertara/joya/core/jdbc/ConnectionCallback.java +++ b/src/main/java/com/sondertara/joya/core/jdbc/ConnectionCallback.java @@ -12,14 +12,13 @@ @FunctionalInterface public interface ConnectionCallback { - /** - * do in transaction - * - * @param conn sql Connection - * @return result - * @throws SQLException e - */ - @Nullable - T doInTransaction(Connection conn) throws SQLException; - + /** + * do in transaction + * + * @param conn sql Connection + * @return result + * @throws SQLException e + */ + @Nullable + T doInTransaction(Connection conn) throws SQLException; } diff --git a/src/main/java/com/sondertara/joya/core/jdbc/ConnectionManager.java b/src/main/java/com/sondertara/joya/core/jdbc/ConnectionManager.java index ba90b2a..2caf767 100644 --- a/src/main/java/com/sondertara/joya/core/jdbc/ConnectionManager.java +++ b/src/main/java/com/sondertara/joya/core/jdbc/ConnectionManager.java @@ -16,153 +16,152 @@ import static com.sondertara.joya.core.constant.JoyaConst.Sql.ORACLE_SET_CURRENT_SCHEMA; /** - * 连接管理器 - * 封装了线程安全的数据库连接 + * 连接管理器 封装了线程安全的数据库连接 * * @author huangxiaohu */ public final class ConnectionManager { - private static final Logger LOG = LoggerFactory.getLogger(JoyaJdbc.class); - private final DataSource dataSource; - private final ThreadLocal connHolder = new ThreadLocal<>(); - - private volatile String defaultCatalog; - - private volatile DbType dbType; - - public ConnectionManager(DataSource dataSource) { - this.dataSource = dataSource; - try (Connection connection = dataSource.getConnection()) { - String productName = connection.getMetaData().getDatabaseProductName(); - if (StringUtils.containsAnyIgnoreCase(productName, DbType.ORACLE.getType())) { - dbType = DbType.ORACLE; - ResultSet resultSet = connection.createStatement().executeQuery(ORACLE_GET_CURRENT_SCHEMA); - if (resultSet.next()) { - this.defaultCatalog = resultSet.getString(1); - } - } else { - this.defaultCatalog = connection.getCatalog(); - } - } catch (SQLException e) { - LOG.error("Get catalog failed.", e); - } - } + private static final Logger LOG = LoggerFactory.getLogger(JoyaJdbc.class); + private final DataSource dataSource; + private final ThreadLocal connHolder = new ThreadLocal<>(); - public void destroy(Consumer consumer) { - consumer.accept(this.dataSource); - } + private volatile String defaultCatalog; - public synchronized Connection getConnection() { - try { - Connection conn = connHolder.get(); - if (conn == null || conn.isClosed()) { - conn = dataSource.getConnection(); - if (null != defaultCatalog) { - if (DbType.ORACLE.equals(dbType)) { - conn.createStatement().execute(ORACLE_SET_CURRENT_SCHEMA.replace("?", defaultCatalog)); - } else { - conn.setCatalog(defaultCatalog); - } - } - connHolder.set(conn); - } - return conn; - } catch (SQLException e) { - throw new DbException("An error occurred while creating a database connection.", e); - } - } + private volatile DbType dbType; - public void close(Connection conn) { - if (conn != null) { - try { - if (conn.getAutoCommit()) { - conn.close(); - connHolder.remove(); - } - } catch (SQLException ignored) { - } + public ConnectionManager(DataSource dataSource) { + this.dataSource = dataSource; + try (Connection connection = dataSource.getConnection()) { + String productName = connection.getMetaData().getDatabaseProductName(); + if (StringUtils.containsAnyIgnoreCase(productName, DbType.ORACLE.getType())) { + dbType = DbType.ORACLE; + ResultSet resultSet = connection.createStatement().executeQuery(ORACLE_GET_CURRENT_SCHEMA); + if (resultSet.next()) { + this.defaultCatalog = resultSet.getString(1); } + } else { + this.defaultCatalog = connection.getCatalog(); + } + } catch (SQLException e) { + LOG.error("Get catalog failed.", e); } - - public void close(Connection conn, Statement stmt, ResultSet rs) { - if (rs != null) { - try { - rs.close(); - } catch (SQLException ignored) { - } - } - if (stmt != null) { - try { - stmt.close(); - } catch (SQLException ignored) { - } - } - if (conn != null) { - try { - if (conn.getAutoCommit()) { - conn.close(); - connHolder.remove(); - } - } catch (SQLException ignored) { - } + } + + public void destroy(Consumer consumer) { + consumer.accept(this.dataSource); + } + + public synchronized Connection getConnection() { + try { + Connection conn = connHolder.get(); + if (conn == null || conn.isClosed()) { + conn = dataSource.getConnection(); + if (null != defaultCatalog) { + if (DbType.ORACLE.equals(dbType)) { + conn.createStatement().execute(ORACLE_SET_CURRENT_SCHEMA.replace("?", defaultCatalog)); + } else { + conn.setCatalog(defaultCatalog); + } } + connHolder.set(conn); + } + return conn; + } catch (SQLException e) { + throw new DbException("An error occurred while creating a database connection.", e); } - - public void startTransaction() { - try { - Connection conn = connHolder.get(); - if (conn != null) { - conn.close(); - connHolder.remove(); - } - conn = dataSource.getConnection(); - if (null != defaultCatalog) { - if (DbType.ORACLE.equals(dbType)) { - conn.createStatement().execute(ORACLE_SET_CURRENT_SCHEMA.replace("?", defaultCatalog)); - } else { - conn.setCatalog(defaultCatalog); - } - } - conn.setAutoCommit(false); - connHolder.set(conn); - } catch (SQLException e) { - throw new DbException("An error occurred while starting transaction.", e); + } + + public void close(Connection conn) { + if (conn != null) { + try { + if (conn.getAutoCommit()) { + conn.close(); + connHolder.remove(); } + } catch (SQLException ignored) { + } } - - public void commit() { - Connection conn = connHolder.get(); - if (conn != null) { - try { - conn.commit(); - conn.close(); - connHolder.remove(); - } catch (SQLException e) { - throw new DbException("An error occurred while committing transaction.", e); - } - } + } + + public void close(Connection conn, Statement stmt, ResultSet rs) { + if (rs != null) { + try { + rs.close(); + } catch (SQLException ignored) { + } } - - public void rollback() { - Connection conn = connHolder.get(); - if (conn != null) { - try { - conn.rollback(); - conn.close(); - connHolder.remove(); - } catch (SQLException e) { - throw new DbException("An error occurred while committing transaction.", e); - } + if (stmt != null) { + try { + stmt.close(); + } catch (SQLException ignored) { + } + } + if (conn != null) { + try { + if (conn.getAutoCommit()) { + conn.close(); + connHolder.remove(); } + } catch (SQLException ignored) { + } } - - public boolean inTransaction() { - Connection conn = connHolder.get(); - try { - return conn != null && !conn.getAutoCommit(); - } catch (SQLException e) { - throw new DbException("An error occurred while getting auto commit.", e); + } + + public void startTransaction() { + try { + Connection conn = connHolder.get(); + if (conn != null) { + conn.close(); + connHolder.remove(); + } + conn = dataSource.getConnection(); + if (null != defaultCatalog) { + if (DbType.ORACLE.equals(dbType)) { + conn.createStatement().execute(ORACLE_SET_CURRENT_SCHEMA.replace("?", defaultCatalog)); + } else { + conn.setCatalog(defaultCatalog); } + } + conn.setAutoCommit(false); + connHolder.set(conn); + } catch (SQLException e) { + throw new DbException("An error occurred while starting transaction.", e); + } + } + + public void commit() { + Connection conn = connHolder.get(); + if (conn != null) { + try { + conn.commit(); + conn.close(); + connHolder.remove(); + } catch (SQLException e) { + throw new DbException("An error occurred while committing transaction.", e); + } + } + } + + public void rollback() { + Connection conn = connHolder.get(); + if (conn != null) { + try { + conn.rollback(); + conn.close(); + connHolder.remove(); + } catch (SQLException e) { + throw new DbException("An error occurred while committing transaction.", e); + } + } + } + + public boolean inTransaction() { + Connection conn = connHolder.get(); + try { + return conn != null && !conn.getAutoCommit(); + } catch (SQLException e) { + throw new DbException("An error occurred while getting auto commit.", e); } + } } diff --git a/src/main/java/com/sondertara/joya/core/jdbc/DbException.java b/src/main/java/com/sondertara/joya/core/jdbc/DbException.java index c65e314..a327c92 100644 --- a/src/main/java/com/sondertara/joya/core/jdbc/DbException.java +++ b/src/main/java/com/sondertara/joya/core/jdbc/DbException.java @@ -6,11 +6,11 @@ * @author huangxiaohu */ public class DbException extends RuntimeException { - public DbException(String msg) { - super(msg); - } + public DbException(String msg) { + super(msg); + } - public DbException(String msg, Throwable cause) { - super(msg, cause); - } + public DbException(String msg, Throwable cause) { + super(msg, cause); + } } diff --git a/src/main/java/com/sondertara/joya/core/jdbc/JoyaJdbc.java b/src/main/java/com/sondertara/joya/core/jdbc/JoyaJdbc.java index 6796105..5231b48 100644 --- a/src/main/java/com/sondertara/joya/core/jdbc/JoyaJdbc.java +++ b/src/main/java/com/sondertara/joya/core/jdbc/JoyaJdbc.java @@ -1,6 +1,5 @@ package com.sondertara.joya.core.jdbc; - import com.sondertara.common.exception.TaraException; import com.sondertara.common.util.StringFormatter; import com.sondertara.joya.cache.TableClassCache; @@ -36,371 +35,380 @@ */ public class JoyaJdbc { - private static final Logger log = LoggerFactory.getLogger(JoyaJdbc.class); - private final ConnectionManager connManager; - - /** - * 创建JdbcUtils - * - * @param dataSource 数据源 - */ - public JoyaJdbc(DataSource dataSource) { - connManager = new ConnectionManager(dataSource); - } - - /** - * 自定义DataSource 销毁 - * - * @param consumer func - */ - public void destroy(Consumer consumer) { - this.connManager.destroy(consumer); - } - - /** - * 判断当前是否在事务中 - */ - public boolean inTransaction() { - return connManager.inTransaction(); - } - - /** - * 查询数据库并转换结果集。 - * 用户可自定义结果集转换器。 - * 用户也可使用预定义的结果集转换器。 - * - * @param sql sql语句 - * @param recordMapper 结果集转换器 - * @param params sql参数 - * @param resultSetMapper返回的结果类型 - * @return 成功则返回转换结果,失败则抛出DbException,结果为空则返回空列表 - * @see RecordMapper - * @see ListRecordMapper - * @see SingleRowRecordMapper - */ - public T query(String sql, RecordMapper recordMapper, Object... params) { - Connection conn = null; - try { - conn = connManager.getConnection(); - try (PreparedStatement stmt = createPreparedStatement(conn, sql, false, params); ResultSet rs = stmt.executeQuery()) { - return recordMapper.map(new RecordAdapterForResultSet(rs)); - } - } catch (Exception e) { - log.error("query sql error,sql:{}", sql, e); - throw new TaraException(e); - } finally { - connManager.close(conn); - } - } - - /** - * 查询数据库,对结果集的每一行进行转换,然后将所有行封装成列表。 - * 用户可自定义行转换器。 - * 用户也可使用预定义的行转换器。 - * - * @param sql sql语句 - * @param rowMapper 行转换器 - * @param params sql参数 - * @param rowMapper返回的结果类型 - * @return 成功则返回结果列表,失败则抛出DbException,结果为空则返回空列表 - * @see RowMapper - * @see BeanRowMapper - * @see MapRowMapper - * @see SingleColumnRowMapper - */ - public List queryList(String sql, RowMapper rowMapper, Object... params) { - return query(sql, new ListRecordMapper<>(rowMapper), params); - } - - /** - * 查询数据库,将结果集的每一行转换成JavaBean,然后将所有行封装成列表。 - * - * @param sql sql语句 - * @param type JavaBean类型 - * @param params sql参数 - * @param JavaBean类型 - * @return 成功则返回结果列表,失败则抛出DbException,结果为空则返回空列表 - */ - public List queryList(String sql, Class type, Object... params) { - return query(sql, new ListRecordMapper<>(new BeanRowMapper<>(type)), params); - } - - /** - * 查询数据库,返回结果集中的单个值。 - * 如果结果集中有多个值,则只返回第一行第一列的值。 - * - * @param sql sql语句 - * @param params sql参数 - * @return 成功则返回结果值,失败则抛出DbException,结果为空则返回null - */ - public T querySingleValue(String sql, Class clazz, Object... params) { - return query(sql, new SingleRowRecordMapper<>(new SingleColumnRowMapper<>(clazz)), params); - } - - /** - * 查询数据库,返回结果集中的单行数据。 - * 如果结果集中有多行数据,则只返回第一行数据。 - * 用户可自定义行转换器。 - * 用户也可使用预定义的行转换器。 - * - * @param sql sql语句 - * @param rowMapper 行转换器 - * @param params sql参数 - * @param rowMapper返回的结果类型 - * @return 成功则返回结果,失败则抛出DbException,结果为空则返回null - * @see RowMapper - * @see BeanRowMapper - * @see MapRowMapper - * @see SingleColumnRowMapper - */ - public T querySingleRow(String sql, RowMapper rowMapper, Object... params) { - return query(sql, new SingleRowRecordMapper<>(rowMapper), params); - } - - /** - * 查询数据库,将结果集中的单行数据转换成JavaBean。 - * - * @param sql sql语句 - * @param type JavaBean类型 - * @param params sql参数 - * @param JavaBean类型 - * @return 成功则返回结果,失败则抛出DbException,结果为空则返回null - */ - public T querySingleRow(String sql, Class type, Object... params) { - return querySingleRow(sql, new BeanRowMapper<>(type), params); - } - - /** - * 更新数据库,返回影响行数 - * - * @param sql sql语句 - * @return 成功则返回影响行数,失败则抛出DbException - */ - public int update(String sql) { - Connection conn = null; - try { - conn = connManager.getConnection(); - try (Statement stmt = conn.createStatement()) { - return stmt.executeUpdate(sql); - } - } catch (Exception e) { - log.error("update sql error,sql:{}", sql, e); - throw new TaraException(e); - } finally { - connManager.close(conn); - } - } - - /** - * 更新数据库,返回影响行数 - * - * @param sql sql语句 - * @param params sql参数 - * @return 成功则返回影响行数,失败则抛出DbException - */ - public int update(String sql, Object[] params) { - Connection conn = null; - try { - conn = connManager.getConnection(); - try (PreparedStatement stmt = createPreparedStatement(conn, sql, false, params);) { - return stmt.executeUpdate(); - } - } catch (Exception e) { - throw new TaraException(e); - } finally { - connManager.close(conn); - } - } - - /** - * 插入数据库,如果是自增主键就返回主键值,否者返回null - * - * @param sql sql语句 - * @param params sql参数 - * @return 成功则返回主键值,失败则抛出DbException - */ - public Object insert(String sql, Object... params) { - Connection conn = null; - try { - conn = connManager.getConnection(); - try (PreparedStatement stmt = createPreparedStatement(conn, sql, true, params)) { - stmt.executeUpdate(); - ResultSet generatedKeys = stmt.getGeneratedKeys(); - if (generatedKeys.next()) { - return generatedKeys.getObject(1); - } - return null; - } - } catch (Exception e) { - throw new TaraException(e); - } finally { - connManager.close(conn); - } + private static final Logger log = LoggerFactory.getLogger(JoyaJdbc.class); + private final ConnectionManager connManager; + + /** + * 创建JdbcUtils + * + * @param dataSource 数据源 + */ + public JoyaJdbc(DataSource dataSource) { + connManager = new ConnectionManager(dataSource); + } + + /** + * 自定义DataSource 销毁 + * + * @param consumer func + */ + public void destroy(Consumer consumer) { + this.connManager.destroy(consumer); + } + + /** 判断当前是否在事务中 */ + public boolean inTransaction() { + return connManager.inTransaction(); + } + + /** + * 查询数据库并转换结果集。 用户可自定义结果集转换器。 用户也可使用预定义的结果集转换器。 + * + * @param sql sql语句 + * @param recordMapper 结果集转换器 + * @param params sql参数 + * @param resultSetMapper返回的结果类型 + * @return 成功则返回转换结果,失败则抛出DbException,结果为空则返回空列表 + * @see RecordMapper + * @see ListRecordMapper + * @see SingleRowRecordMapper + */ + public T query(String sql, RecordMapper recordMapper, Object... params) { + Connection conn = null; + try { + conn = connManager.getConnection(); + try (PreparedStatement stmt = createPreparedStatement(conn, sql, false, params); + ResultSet rs = stmt.executeQuery()) { + return recordMapper.map(new RecordAdapterForResultSet(rs)); + } + } catch (Exception e) { + log.error("query sql error,sql:{}", sql, e); + throw new TaraException(e); + } finally { + connManager.close(conn); } - - public Object saveEntityIgnoreNull(T entity) { - TableEntity table = TableClassCache.getInstance().getTable(entity, true); - Map data = table.getData(); - Map newData = new LinkedHashMap<>(); - for (Map.Entry entry : data.entrySet()) { - if (entry.getValue() != null) { - newData.put(entry.getKey(), entry.getValue()); - } - } - table.setData(newData); - return save(table); + } + + /** + * 查询数据库,对结果集的每一行进行转换,然后将所有行封装成列表。 用户可自定义行转换器。 用户也可使用预定义的行转换器。 + * + * @param sql sql语句 + * @param rowMapper 行转换器 + * @param params sql参数 + * @param rowMapper返回的结果类型 + * @return 成功则返回结果列表,失败则抛出DbException,结果为空则返回空列表 + * @see RowMapper + * @see BeanRowMapper + * @see MapRowMapper + * @see SingleColumnRowMapper + */ + public List queryList(String sql, RowMapper rowMapper, Object... params) { + return query(sql, new ListRecordMapper<>(rowMapper), params); + } + + /** + * 查询数据库,将结果集的每一行转换成JavaBean,然后将所有行封装成列表。 + * + * @param sql sql语句 + * @param type JavaBean类型 + * @param params sql参数 + * @param JavaBean类型 + * @return 成功则返回结果列表,失败则抛出DbException,结果为空则返回空列表 + */ + public List queryList(String sql, Class type, Object... params) { + return query(sql, new ListRecordMapper<>(new BeanRowMapper<>(type)), params); + } + + /** + * 查询数据库,返回结果集中的单个值。 如果结果集中有多个值,则只返回第一行第一列的值。 + * + * @param sql sql语句 + * @param params sql参数 + * @return 成功则返回结果值,失败则抛出DbException,结果为空则返回null + */ + public T querySingleValue(String sql, Class clazz, Object... params) { + return query(sql, new SingleRowRecordMapper<>(new SingleColumnRowMapper<>(clazz)), params); + } + + /** + * 查询数据库,返回结果集中的单行数据。 如果结果集中有多行数据,则只返回第一行数据。 用户可自定义行转换器。 用户也可使用预定义的行转换器。 + * + * @param sql sql语句 + * @param rowMapper 行转换器 + * @param params sql参数 + * @param rowMapper返回的结果类型 + * @return 成功则返回结果,失败则抛出DbException,结果为空则返回null + * @see RowMapper + * @see BeanRowMapper + * @see MapRowMapper + * @see SingleColumnRowMapper + */ + public T querySingleRow(String sql, RowMapper rowMapper, Object... params) { + return query(sql, new SingleRowRecordMapper<>(rowMapper), params); + } + + /** + * 查询数据库,将结果集中的单行数据转换成JavaBean。 + * + * @param sql sql语句 + * @param type JavaBean类型 + * @param params sql参数 + * @param JavaBean类型 + * @return 成功则返回结果,失败则抛出DbException,结果为空则返回null + */ + public T querySingleRow(String sql, Class type, Object... params) { + return querySingleRow(sql, new BeanRowMapper<>(type), params); + } + + /** + * 更新数据库,返回影响行数 + * + * @param sql sql语句 + * @return 成功则返回影响行数,失败则抛出DbException + */ + public int update(String sql) { + Connection conn = null; + try { + conn = connManager.getConnection(); + try (Statement stmt = conn.createStatement()) { + return stmt.executeUpdate(sql); + } + } catch (Exception e) { + log.error("update sql error,sql:{}", sql, e); + throw new TaraException(e); + } finally { + connManager.close(conn); } - - - public Object saveEntity(T entity) { - TableEntity table = TableClassCache.getInstance().getTable(entity, true); - return save(table); - + } + + /** + * 更新数据库,返回影响行数 + * + * @param sql sql语句 + * @param params sql参数 + * @return 成功则返回影响行数,失败则抛出DbException + */ + public int update(String sql, Object[] params) { + Connection conn = null; + try { + conn = connManager.getConnection(); + try (PreparedStatement stmt = createPreparedStatement(conn, sql, false, params); ) { + return stmt.executeUpdate(); + } + } catch (Exception e) { + throw new TaraException(e); + } finally { + connManager.close(conn); } - - - /** - * 执行sql命令, 失败则抛出DbException - * - * @param sql sql语句 - */ - public void execute(String sql) { - Connection conn = null; - try { - conn = connManager.getConnection(); - try (Statement stmt = conn.createStatement()) { - stmt.execute(sql); - } - } catch (Exception e) { - log.error("execute sql error,sql:{}", sql, e); - throw new TaraException(e); - } finally { - connManager.close(conn); + } + + /** + * 插入数据库,如果是自增主键就返回主键值,否者返回null + * + * @param sql sql语句 + * @param params sql参数 + * @return 成功则返回主键值,失败则抛出DbException + */ + public Object insert(String sql, Object... params) { + Connection conn = null; + try { + conn = connManager.getConnection(); + try (PreparedStatement stmt = createPreparedStatement(conn, sql, true, params)) { + stmt.executeUpdate(); + ResultSet generatedKeys = stmt.getGeneratedKeys(); + if (generatedKeys.next()) { + return generatedKeys.getObject(1); } + return null; + } + } catch (Exception e) { + throw new TaraException(e); + } finally { + connManager.close(conn); } - - public Connection getConnection() { - return connManager.getConnection(); + } + + public Object saveEntityIgnoreNull(T entity) { + TableEntity table = TableClassCache.getInstance().getTable(entity, true); + Map data = table.getData(); + Map newData = new LinkedHashMap<>(); + for (Map.Entry entry : data.entrySet()) { + if (entry.getValue() != null) { + newData.put(entry.getKey(), entry.getValue()); + } } - - /** - * 开启事务 - */ - public Connection startTransaction() { - connManager.startTransaction(); - return connManager.getConnection(); + table.setData(newData); + return save(table); + } + + public Object saveEntity(T entity) { + TableEntity table = TableClassCache.getInstance().getTable(entity, true); + return save(table); + } + + /** + * 执行sql命令, 失败则抛出DbException + * + * @param sql sql语句 + */ + public void execute(String sql) { + Connection conn = null; + try { + conn = connManager.getConnection(); + try (Statement stmt = conn.createStatement()) { + stmt.execute(sql); + } + } catch (Exception e) { + log.error("execute sql error,sql:{}", sql, e); + throw new TaraException(e); + } finally { + connManager.close(conn); } - - /** - * 提交事务 - */ - public void commit() { - connManager.commit(); + } + + public Connection getConnection() { + return connManager.getConnection(); + } + + /** 开启事务 */ + public Connection startTransaction() { + connManager.startTransaction(); + return connManager.getConnection(); + } + + /** 提交事务 */ + public void commit() { + connManager.commit(); + } + + /** 回滚事务 */ + public void rollback() { + connManager.rollback(); + } + + /** + * run transaction with connection + * + * @param action callback + * @param callback type + * @return result + */ + public T doInTransaction(ConnectionCallback action) { + + Connection conn = null; + try { + conn = this.startTransaction(); + T t = action.doInTransaction(conn); + this.commit(); + return t; + } catch (Exception e) { + log.error("TransactionCallback", e); + this.rollback(); + throw new TaraException(e); } - - /** - * 回滚事务 - */ - public void rollback() { - connManager.rollback(); + } + + /** + * run transaction with statement. + * + * @param action statement callback + * @param type of result + * @return result + */ + public T doInStatement(StatementCallback action) { + Connection conn = null; + try { + conn = this.startTransaction(); + try (Statement stmt = conn.createStatement()) { + T t = action.doInStatement(stmt); + this.commit(); + return t; + } + } catch (Exception e) { + log.error("TransactionCallback", e); + throw new TaraException(e); + } finally { + connManager.close(conn); } - - /** - * run transaction with connection - * - * @param action callback - * @param callback type - * @return result - */ - public T doInTransaction(ConnectionCallback action) { - - Connection conn = null; - try { - conn = this.startTransaction(); - T t = action.doInTransaction(conn); - this.commit(); - return t; - } catch (Exception e) { - log.error("TransactionCallback", e); - this.rollback(); - throw new TaraException(e); - } + } + + /** + * 创建语句 + * + * @param conn 连接 + * @param sql sql语句 + * @param params sql参数 + * @return 创建的PreparedStatement对象 + * @throws SQLException 来自JDBC的异常 + */ + private PreparedStatement createPreparedStatement( + Connection conn, String sql, boolean autoGeneratedKeys, Object... params) + throws SQLException { + PreparedStatement stmt = null; + if (autoGeneratedKeys) { + stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS); + } else { + stmt = conn.prepareStatement(sql); } - - /** - * run transaction with statement. - * - * @param action statement callback - * @param type of result - * @return result - */ - public T doInStatement(StatementCallback action) { - Connection conn = null; - try { - conn = this.startTransaction(); - try (Statement stmt = conn.createStatement()) { - T t = action.doInStatement(stmt); - this.commit(); - return t; - } - } catch (Exception e) { - log.error("TransactionCallback", e); - throw new TaraException(e); - } finally { - connManager.close(conn); - } + if (null != params && params.length > 0) { + for (int i = 0; i < params.length; ++i) { + stmt.setObject(i + 1, params[i]); + } } - - - /** - * 创建语句 - * - * @param conn 连接 - * @param sql sql语句 - * @param params sql参数 - * @return 创建的PreparedStatement对象 - * @throws SQLException 来自JDBC的异常 - */ - private PreparedStatement createPreparedStatement(Connection conn, String sql, boolean autoGeneratedKeys, Object... params) throws SQLException { - PreparedStatement stmt = null; - if (autoGeneratedKeys) { - stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS); - } else { - stmt = conn.prepareStatement(sql); - } - if (null != params && params.length > 0) { - for (int i = 0; i < params.length; ++i) { - stmt.setObject(i + 1, params[i]); - } - } - return stmt; + return stmt; + } + + private Object save(TableEntity table) { + Map data = table.getData(); + if (null == data.get(table.getPrimaryKey())) { + data.remove(table.getPrimaryKey()); + List set = data.keySet().stream().map(s -> "?").collect(Collectors.toList()); + return insert( + StringFormatter.format( + "insert into {}({}) values({})", + table.getTableName(), + String.join(",", data.keySet()), + String.join(",", set)), + data.values().toArray()); } - - private Object save(TableEntity table) { - Map data = table.getData(); - if (null == data.get(table.getPrimaryKey())) { - data.remove(table.getPrimaryKey()); - List set = data.keySet().stream().map(s -> "?").collect(Collectors.toList()); - return insert(StringFormatter.format("insert into {}({}) values({})", table.getTableName(), String.join(",", data.keySet()), String.join(",", set)), data.values().toArray()); - } - Object value = querySingleValue(StringFormatter.format("select {} from {} where {} = ?", table.getPrimaryKey(), table.getTableName(), table.getPrimaryKey()), Object.class, data.get(table.getPrimaryKey())); - List set = data.keySet().stream().map(s -> "?").collect(Collectors.toList()); - if (null == value) { - insert(StringFormatter.format("insert into {}({}) values({})", table.getTableName(), String.join(",", data.keySet()), String.join(",", set)), data.values().toArray()); - return data.get(table.getPrimaryKey()); - } else { - StringJoiner sj = new StringJoiner(", "); - List values = new ArrayList<>(); - for (Map.Entry entry : data.entrySet()) { - if (entry.getKey().equals(table.getPrimaryKey())) { - continue; - } - sj.add(entry.getKey() + " = ?"); - values.add(entry.getValue()); - } - values.add(data.get(table.getPrimaryKey())); - update(StringFormatter.format("update {} set {} where {} = ?", table.getTableName(), sj.toString(), table.getPrimaryKey()), values.toArray()); - return data.get(table.getPrimaryKey()); + Object value = + querySingleValue( + StringFormatter.format( + "select {} from {} where {} = ?", + table.getPrimaryKey(), + table.getTableName(), + table.getPrimaryKey()), + Object.class, + data.get(table.getPrimaryKey())); + List set = data.keySet().stream().map(s -> "?").collect(Collectors.toList()); + if (null == value) { + insert( + StringFormatter.format( + "insert into {}({}) values({})", + table.getTableName(), + String.join(",", data.keySet()), + String.join(",", set)), + data.values().toArray()); + return data.get(table.getPrimaryKey()); + } else { + StringJoiner sj = new StringJoiner(", "); + List values = new ArrayList<>(); + for (Map.Entry entry : data.entrySet()) { + if (entry.getKey().equals(table.getPrimaryKey())) { + continue; } + sj.add(entry.getKey() + " = ?"); + values.add(entry.getValue()); + } + values.add(data.get(table.getPrimaryKey())); + update( + StringFormatter.format( + "update {} set {} where {} = ?", + table.getTableName(), + sj.toString(), + table.getPrimaryKey()), + values.toArray()); + return data.get(table.getPrimaryKey()); } + } } diff --git a/src/main/java/com/sondertara/joya/core/jdbc/Record.java b/src/main/java/com/sondertara/joya/core/jdbc/Record.java index c85a0b8..d54dba8 100644 --- a/src/main/java/com/sondertara/joya/core/jdbc/Record.java +++ b/src/main/java/com/sondertara/joya/core/jdbc/Record.java @@ -1,28 +1,24 @@ package com.sondertara.joya.core.jdbc; /** - * 结果集:对数据库查询操作返回结果的封装。 - * 一个结果集由若干个数据行组成。 - * 初始时,结果集的当前行指向第一行之前。 - * 调用next方法可以让当前行向前移动一行。 - * 若当前已到达最后一行,则next调用返回false,否则返回true。 - * 结果集的当前行只能向前移动,不能向后移动。 + * 结果集:对数据库查询操作返回结果的封装。 一个结果集由若干个数据行组成。 初始时,结果集的当前行指向第一行之前。 调用next方法可以让当前行向前移动一行。 + * 若当前已到达最后一行,则next调用返回false,否则返回true。 结果集的当前行只能向前移动,不能向后移动。 * * @author huangxiaohu * @see Row */ public interface Record { - /** - * 获取当前行 - * - * @return 当前行 - */ - Row getCurrentRow(); + /** + * 获取当前行 + * + * @return 当前行 + */ + Row getCurrentRow(); - /** - * 移动到下一行 - * - * @return 若当前已到达最后一行,则返回false,否则返回true - */ - boolean next(); + /** + * 移动到下一行 + * + * @return 若当前已到达最后一行,则返回false,否则返回true + */ + boolean next(); } diff --git a/src/main/java/com/sondertara/joya/core/jdbc/RecordAdapterForResultSet.java b/src/main/java/com/sondertara/joya/core/jdbc/RecordAdapterForResultSet.java index c781e2e..dc7cc87 100644 --- a/src/main/java/com/sondertara/joya/core/jdbc/RecordAdapterForResultSet.java +++ b/src/main/java/com/sondertara/joya/core/jdbc/RecordAdapterForResultSet.java @@ -12,187 +12,187 @@ * @author huangxiaohu */ public class RecordAdapterForResultSet implements Record, Row { - private final ResultSet rs; - - public RecordAdapterForResultSet(ResultSet resultSet) { - this.rs = resultSet; - } - - @Override - public Object getObject(String columnLabel) { - try { - return rs.getObject(columnLabel); - } catch (SQLException e) { - throw new RuntimeException(e.getMessage(), e); - } - } - - @Override - public Object getObject(int columnIndex) { - try { - return rs.getObject(columnIndex); - } catch (SQLException e) { - throw new RuntimeException(e.getMessage(), e); - } - } - - @Override - public int getInt(String columnLabel) { - try { - return rs.getInt(columnLabel); - } catch (SQLException e) { - throw new RuntimeException(e.getMessage(), e); - } - } - - @Override - public int getInt(int columnIndex) { - try { - return rs.getInt(columnIndex); - } catch (SQLException e) { - throw new RuntimeException(e.getMessage(), e); - } - } - - @Override - public boolean getBoolean(int columnIndex) { - try { - return rs.getBoolean(columnIndex); - } catch (SQLException e) { - throw new RuntimeException(e.getMessage(), e); - } - } - - @Override - public boolean getBoolean(String columnLabel) { - try { - return rs.getBoolean(columnLabel); - } catch (SQLException e) { - throw new RuntimeException(e.getMessage(), e); - } - } - - @Override - public String getString(String columnLabel) { - try { - return rs.getString(columnLabel); - } catch (SQLException e) { - throw new RuntimeException(e.getMessage(), e); - } - } - - @Override - public String getString(int columnIndex) { - try { - return rs.getString(columnIndex); - } catch (SQLException e) { - throw new RuntimeException(e.getMessage(), e); - } - } - - @Override - public double getDouble(String columnLabel) { - try { - return rs.getDouble(columnLabel); - } catch (SQLException e) { - throw new RuntimeException(e.getMessage(), e); - } - } - - @Override - public double getDouble(int columnIndex) { - try { - return rs.getDouble(columnIndex); - } catch (SQLException e) { - throw new RuntimeException(e.getMessage(), e); - } - } - - @Override - public int getColumnCount() { - try { - ResultSetMetaData metaData = rs.getMetaData(); - return metaData.getColumnCount(); - } catch (SQLException e) { - throw new RuntimeException(e.getMessage(), e); - } - } - - @Override - public String getColumnLabel(int index) { - try { - ResultSetMetaData metaData = rs.getMetaData(); - return metaData.getColumnLabel(index); - } catch (SQLException e) { - throw new RuntimeException(e.getMessage(), e); - } - } - - @Override - public Row getCurrentRow() { - return this; - } - - @Override - public boolean next() { - try { - return rs.next(); - } catch (SQLException e) { - throw new RuntimeException(e.getMessage(), e); - } - } - - @Override - public long getLong(String columnLabel) { - try { - return rs.getLong(columnLabel); - } catch (SQLException e) { - throw new RuntimeException(e.getMessage(), e); - } - } - - @Override - public long getLong(int columnIndex) { - try { - return rs.getLong(columnIndex); - } catch (SQLException e) { - throw new RuntimeException(e.getMessage(), e); - } - } - - @Override - public BigDecimal getBigDecimal(String columnLabel) { - try { - return rs.getBigDecimal(columnLabel); - } catch (SQLException e) { - throw new RuntimeException(e.getMessage(), e); - } - } - - @Override - public BigDecimal getBigDecimal(int columnIndex) { - try { - return rs.getBigDecimal(columnIndex); - } catch (SQLException e) { - throw new RuntimeException(e.getMessage(), e); - } - } - - @Override - public Date getDate(String columnLabel) { - try { - return rs.getDate(columnLabel); - } catch (SQLException e) { - throw new RuntimeException(e.getMessage(), e); - } - } - - @Override - public Date getDate(int columnIndex) { - try { - return rs.getDate(columnIndex); - } catch (SQLException e) { - throw new RuntimeException(e.getMessage(), e); - } - } + private final ResultSet rs; + + public RecordAdapterForResultSet(ResultSet resultSet) { + this.rs = resultSet; + } + + @Override + public Object getObject(String columnLabel) { + try { + return rs.getObject(columnLabel); + } catch (SQLException e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + @Override + public Object getObject(int columnIndex) { + try { + return rs.getObject(columnIndex); + } catch (SQLException e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + @Override + public int getInt(String columnLabel) { + try { + return rs.getInt(columnLabel); + } catch (SQLException e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + @Override + public int getInt(int columnIndex) { + try { + return rs.getInt(columnIndex); + } catch (SQLException e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + @Override + public boolean getBoolean(int columnIndex) { + try { + return rs.getBoolean(columnIndex); + } catch (SQLException e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + @Override + public boolean getBoolean(String columnLabel) { + try { + return rs.getBoolean(columnLabel); + } catch (SQLException e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + @Override + public String getString(String columnLabel) { + try { + return rs.getString(columnLabel); + } catch (SQLException e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + @Override + public String getString(int columnIndex) { + try { + return rs.getString(columnIndex); + } catch (SQLException e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + @Override + public double getDouble(String columnLabel) { + try { + return rs.getDouble(columnLabel); + } catch (SQLException e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + @Override + public double getDouble(int columnIndex) { + try { + return rs.getDouble(columnIndex); + } catch (SQLException e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + @Override + public int getColumnCount() { + try { + ResultSetMetaData metaData = rs.getMetaData(); + return metaData.getColumnCount(); + } catch (SQLException e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + @Override + public String getColumnLabel(int index) { + try { + ResultSetMetaData metaData = rs.getMetaData(); + return metaData.getColumnLabel(index); + } catch (SQLException e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + @Override + public Row getCurrentRow() { + return this; + } + + @Override + public boolean next() { + try { + return rs.next(); + } catch (SQLException e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + @Override + public long getLong(String columnLabel) { + try { + return rs.getLong(columnLabel); + } catch (SQLException e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + @Override + public long getLong(int columnIndex) { + try { + return rs.getLong(columnIndex); + } catch (SQLException e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + @Override + public BigDecimal getBigDecimal(String columnLabel) { + try { + return rs.getBigDecimal(columnLabel); + } catch (SQLException e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + @Override + public BigDecimal getBigDecimal(int columnIndex) { + try { + return rs.getBigDecimal(columnIndex); + } catch (SQLException e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + @Override + public Date getDate(String columnLabel) { + try { + return rs.getDate(columnLabel); + } catch (SQLException e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + @Override + public Date getDate(int columnIndex) { + try { + return rs.getDate(columnIndex); + } catch (SQLException e) { + throw new RuntimeException(e.getMessage(), e); + } + } } diff --git a/src/main/java/com/sondertara/joya/core/jdbc/Row.java b/src/main/java/com/sondertara/joya/core/jdbc/Row.java index 41193c2..48b5383 100644 --- a/src/main/java/com/sondertara/joya/core/jdbc/Row.java +++ b/src/main/java/com/sondertara/joya/core/jdbc/Row.java @@ -4,143 +4,140 @@ import java.util.Date; /** - * 数据行:封装了结果集的一行数据。 - * 数据行由若干列组成,每列都是一个值。 - * Row通过Record的getCurrentRow方法获取。 - * Row中包含了一系列getXXX方法用于获取列中的值。 + * 数据行:封装了结果集的一行数据。 数据行由若干列组成,每列都是一个值。 Row通过Record的getCurrentRow方法获取。 Row中包含了一系列getXXX方法用于获取列中的值。 * * @author huangxiaohu * @see Record */ public interface Row { - /** - * get obj - * - * @param columnLabel column - * @return column of one row - */ - Object getObject(String columnLabel); - - /** - * get obj - * - * @param columnIndex column index - * @return column of one row - */ - Object getObject(int columnIndex); - - /** - * get long - * - * @param columnLabel name - * @return long - */ - long getLong(String columnLabel); - - /** - * long - * - * @param columnIndex index - * @return long - */ - long getLong(int columnIndex); - - /** - * get int - * - * @param columnLabel name - * @return int - */ - int getInt(String columnLabel); - - /** - * int - * - * @param columnIndex index - * @return i - */ - int getInt(int columnIndex); - - boolean getBoolean(int columnIndex); - - boolean getBoolean(String columnLabel); - - /** - * get int - * - * @param columnLabel name - * @return int - */ - BigDecimal getBigDecimal(String columnLabel); - - /** - * int - * - * @param columnIndex index - * @return i - */ - BigDecimal getBigDecimal(int columnIndex); - - /** - * get int - * - * @param columnLabel name - * @return int - */ - Date getDate(String columnLabel); - - /** - * int - * - * @param columnIndex index - * @return i - */ - Date getDate(int columnIndex); - - /** - * get str - * - * @param columnLabel name - * @return s - */ - String getString(String columnLabel); - - /** - * get str - * - * @param columnIndex index - * @return s - */ - String getString(int columnIndex); - - /** - * get double - * - * @param columnLabel name - * @return d - */ - double getDouble(String columnLabel); - - /** - * get double - * - * @param columnIndex i - * @return d - */ - double getDouble(int columnIndex); - - /** - * 获取列数 - * - * @return 列数 - */ - int getColumnCount(); - - /** - * 获取列标签 - * - * @param index 列索引(从1开始) - * @return 列标签 - */ - String getColumnLabel(int index); + /** + * get obj + * + * @param columnLabel column + * @return column of one row + */ + Object getObject(String columnLabel); + + /** + * get obj + * + * @param columnIndex column index + * @return column of one row + */ + Object getObject(int columnIndex); + + /** + * get long + * + * @param columnLabel name + * @return long + */ + long getLong(String columnLabel); + + /** + * long + * + * @param columnIndex index + * @return long + */ + long getLong(int columnIndex); + + /** + * get int + * + * @param columnLabel name + * @return int + */ + int getInt(String columnLabel); + + /** + * int + * + * @param columnIndex index + * @return i + */ + int getInt(int columnIndex); + + boolean getBoolean(int columnIndex); + + boolean getBoolean(String columnLabel); + + /** + * get int + * + * @param columnLabel name + * @return int + */ + BigDecimal getBigDecimal(String columnLabel); + + /** + * int + * + * @param columnIndex index + * @return i + */ + BigDecimal getBigDecimal(int columnIndex); + + /** + * get int + * + * @param columnLabel name + * @return int + */ + Date getDate(String columnLabel); + + /** + * int + * + * @param columnIndex index + * @return i + */ + Date getDate(int columnIndex); + + /** + * get str + * + * @param columnLabel name + * @return s + */ + String getString(String columnLabel); + + /** + * get str + * + * @param columnIndex index + * @return s + */ + String getString(int columnIndex); + + /** + * get double + * + * @param columnLabel name + * @return d + */ + double getDouble(String columnLabel); + + /** + * get double + * + * @param columnIndex i + * @return d + */ + double getDouble(int columnIndex); + + /** + * 获取列数 + * + * @return 列数 + */ + int getColumnCount(); + + /** + * 获取列标签 + * + * @param index 列索引(从1开始) + * @return 列标签 + */ + String getColumnLabel(int index); } diff --git a/src/main/java/com/sondertara/joya/core/jdbc/SqlDataHelper.java b/src/main/java/com/sondertara/joya/core/jdbc/SqlDataHelper.java index 63ef3e2..e9495b1 100644 --- a/src/main/java/com/sondertara/joya/core/jdbc/SqlDataHelper.java +++ b/src/main/java/com/sondertara/joya/core/jdbc/SqlDataHelper.java @@ -29,210 +29,206 @@ */ public final class SqlDataHelper { - private static final Logger LOG = LoggerFactory.getLogger(SqlDataHelper.class); + private static final Logger LOG = LoggerFactory.getLogger(SqlDataHelper.class); - private SqlDataHelper() { - } + private SqlDataHelper() {} - /** - * The size of the buffer we will use to deserialize larger streams - */ - private static final int BUFFER_SIZE = 1024 * 4; + /** The size of the buffer we will use to deserialize larger streams */ + private static final int BUFFER_SIZE = 1024 * 4; + public static boolean isNClob(final Class type) { + return java.sql.NClob.class.isAssignableFrom(type); + } - public static boolean isNClob(final Class type) { - return java.sql.NClob.class.isAssignableFrom(type); - } + public static boolean isClob(final Class type) { + return Clob.class.isAssignableFrom(type); + } - public static boolean isClob(final Class type) { - return Clob.class.isAssignableFrom(type); + public static Object extractDate(Object timestamp) { + // convert Oracle TIMESTAMP + if (timestamp instanceof TIMESTAMP) { + try { + return ((TIMESTAMP) timestamp).timestampValue(Calendar.getInstance(TimeZone.getDefault())); + } catch (SQLException e) { + throw new TaraException(e); + } } - - public static Object extractDate(Object timestamp) { - // convert Oracle TIMESTAMP - if (timestamp instanceof TIMESTAMP) { - try { - return ((TIMESTAMP) timestamp).timestampValue(Calendar.getInstance(TimeZone.getDefault())); - } catch (SQLException e) { - throw new TaraException(e); - } + return timestamp; + } + + /** + * Extract the contents of the given reader/stream as a string. The reader will be closed. + * + * @param reader The reader for the content + * @return The content as string + */ + public static String extractString(Reader reader) { + return extractString(reader, BUFFER_SIZE); + } + + /** + * Extract the contents of the given reader/stream as a string. The reader will be closed. + * + * @param reader The reader for the content + * @param lengthHint if the length is known in advance the implementation can be slightly more + * efficient + * @return The content as string + */ + public static String extractString(Reader reader, int lengthHint) { + // read the Reader contents into a buffer and return the complete string + final int bufferSize = getSuggestedBufferSize(lengthHint); + final StringBuilder stringBuilder = new StringBuilder(bufferSize); + try { + char[] buffer = new char[bufferSize]; + while (true) { + int amountRead = reader.read(buffer, 0, bufferSize); + if (amountRead == -1) { + break; } - return timestamp; + stringBuilder.append(buffer, 0, amountRead); + } + } catch (IOException ioe) { + throw new TaraException("IOException occurred reading text", ioe); + } finally { + try { + reader.close(); + } catch (IOException e) { + LOG.error("", e); + } } - - /** - * Extract the contents of the given reader/stream as a string. - * The reader will be closed. - * - * @param reader The reader for the content - * @return The content as string - */ - public static String extractString(Reader reader) { - return extractString(reader, BUFFER_SIZE); + return stringBuilder.toString(); + } + + /** + * Extracts a portion of the contents of the given reader/stream as a string. + * + * @param characterStream The reader for the content + * @param start The start position/offset (0-based, per general stream/reader contracts). + * @param length The amount to extract + * @return The content as string + */ + private static String extractString(Reader characterStream, long start, int length) { + if (length == 0) { + return ""; } - - /** - * Extract the contents of the given reader/stream as a string. - * The reader will be closed. - * - * @param reader The reader for the content - * @param lengthHint if the length is known in advance the implementation can be slightly more efficient - * @return The content as string - */ - public static String extractString(Reader reader, int lengthHint) { - // read the Reader contents into a buffer and return the complete string - final int bufferSize = getSuggestedBufferSize(lengthHint); - final StringBuilder stringBuilder = new StringBuilder(bufferSize); - try { - char[] buffer = new char[bufferSize]; - while (true) { - int amountRead = reader.read(buffer, 0, bufferSize); - if (amountRead == -1) { - break; - } - stringBuilder.append(buffer, 0, amountRead); - } - } catch (IOException ioe) { - throw new TaraException("IOException occurred reading text", ioe); - } finally { - try { - reader.close(); - } catch (IOException e) { - LOG.error("", e); - } + StringBuilder stringBuilder = new StringBuilder(length); + try { + long skipped = characterStream.skip(start); + if (skipped != start) { + throw new TaraException("Unable to skip needed bytes"); + } + final int bufferSize = getSuggestedBufferSize(length); + char[] buffer = new char[bufferSize]; + int charsRead = 0; + while (true) { + int amountRead = characterStream.read(buffer, 0, bufferSize); + if (amountRead == -1) { + break; } - return stringBuilder.toString(); - } - - /** - * Extracts a portion of the contents of the given reader/stream as a string. - * - * @param characterStream The reader for the content - * @param start The start position/offset (0-based, per general stream/reader contracts). - * @param length The amount to extract - * @return The content as string - */ - private static String extractString(Reader characterStream, long start, int length) { - if (length == 0) { - return ""; + stringBuilder.append(buffer, 0, amountRead); + if (amountRead < bufferSize) { + // we have read up to the end of stream + break; } - StringBuilder stringBuilder = new StringBuilder(length); - try { - long skipped = characterStream.skip(start); - if (skipped != start) { - throw new TaraException("Unable to skip needed bytes"); - } - final int bufferSize = getSuggestedBufferSize(length); - char[] buffer = new char[bufferSize]; - int charsRead = 0; - while (true) { - int amountRead = characterStream.read(buffer, 0, bufferSize); - if (amountRead == -1) { - break; - } - stringBuilder.append(buffer, 0, amountRead); - if (amountRead < bufferSize) { - // we have read up to the end of stream - break; - } - charsRead += amountRead; - if (charsRead >= length) { - break; - } - } - } catch (IOException ioe) { - throw new TaraException("IOException occurred reading a binary value", ioe); + charsRead += amountRead; + if (charsRead >= length) { + break; } - return stringBuilder.toString(); - } - - /** - * Extract a portion of a reader, wrapping the portion in a new reader. - * - * @param characterStream The reader for the content - * @param start The start position/offset (0-based, per general stream/reader contracts). - * @param length The amount to extract - * @return The content portion as a reader - */ - public static Object subStream(Reader characterStream, long start, int length) { - return new StringReader(extractString(characterStream, start, length)); + } + } catch (IOException ioe) { + throw new TaraException("IOException occurred reading a binary value", ioe); } - - /** - * Extract by bytes from the given stream. - * - * @param inputStream The stream of bytes. - * @return The contents as a {@code byte[]} - */ - public static byte[] extractBytes(InputStream inputStream) { - - // read the stream contents into a buffer and return the complete byte[] - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(BUFFER_SIZE); - try { - byte[] buffer = new byte[BUFFER_SIZE]; - while (true) { - int amountRead = inputStream.read(buffer); - if (amountRead == -1) { - break; - } - outputStream.write(buffer, 0, amountRead); - } - } catch (IOException ioe) { - throw new TaraException("IOException occurred reading a binary value", ioe); - } finally { - try { - inputStream.close(); - } catch (IOException e) { - LOG.error("", e); - } - try { - outputStream.close(); - } catch (IOException e) { - LOG.error("Close Stream", e); - } - } - return outputStream.toByteArray(); - } - - - /** - * Extract the contents of the given Clob as a string. - * - * @param value The clob to to be extracted from - * @return The content as string - */ - public static String extractString(final Clob value) { - try { - final Reader characterStream = value.getCharacterStream(); - final long length = determineLengthForBufferSizing(value); - return length > Integer.MAX_VALUE ? extractString(characterStream, Integer.MAX_VALUE) : extractString(characterStream, (int) length); - } catch (SQLException e) { - throw new TaraException("Unable to access lob stream", e); + return stringBuilder.toString(); + } + + /** + * Extract a portion of a reader, wrapping the portion in a new reader. + * + * @param characterStream The reader for the content + * @param start The start position/offset (0-based, per general stream/reader contracts). + * @param length The amount to extract + * @return The content portion as a reader + */ + public static Object subStream(Reader characterStream, long start, int length) { + return new StringReader(extractString(characterStream, start, length)); + } + + /** + * Extract by bytes from the given stream. + * + * @param inputStream The stream of bytes. + * @return The contents as a {@code byte[]} + */ + public static byte[] extractBytes(InputStream inputStream) { + + // read the stream contents into a buffer and return the complete byte[] + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(BUFFER_SIZE); + try { + byte[] buffer = new byte[BUFFER_SIZE]; + while (true) { + int amountRead = inputStream.read(buffer); + if (amountRead == -1) { + break; } + outputStream.write(buffer, 0, amountRead); + } + } catch (IOException ioe) { + throw new TaraException("IOException occurred reading a binary value", ioe); + } finally { + try { + inputStream.close(); + } catch (IOException e) { + LOG.error("", e); + } + try { + outputStream.close(); + } catch (IOException e) { + LOG.error("Close Stream", e); + } } - - /** - * Determine a buffer size for reading the underlying character stream. - * - * @param value The Clob value - * @return The appropriate buffer size ({@link Clob#length()} by default. - */ - private static long determineLengthForBufferSizing(Clob value) throws SQLException { - try { - return value.length(); - } catch (SQLFeatureNotSupportedException e) { - return BUFFER_SIZE; - } + return outputStream.toByteArray(); + } + + /** + * Extract the contents of the given Clob as a string. + * + * @param value The clob to to be extracted from + * @return The content as string + */ + public static String extractString(final Clob value) { + try { + final Reader characterStream = value.getCharacterStream(); + final long length = determineLengthForBufferSizing(value); + return length > Integer.MAX_VALUE + ? extractString(characterStream, Integer.MAX_VALUE) + : extractString(characterStream, (int) length); + } catch (SQLException e) { + throw new TaraException("Unable to access lob stream", e); } - - /** - * Make sure we allocate a buffer sized not bigger than 2048, - * not higher than what is actually needed, and at least one. - * - * @param lengthHint the expected size of the full value - * @return the buffer size - */ - private static int getSuggestedBufferSize(final int lengthHint) { - return Math.max(1, Math.min(lengthHint, BUFFER_SIZE)); + } + + /** + * Determine a buffer size for reading the underlying character stream. + * + * @param value The Clob value + * @return The appropriate buffer size ({@link Clob#length()} by default. + */ + private static long determineLengthForBufferSizing(Clob value) throws SQLException { + try { + return value.length(); + } catch (SQLFeatureNotSupportedException e) { + return BUFFER_SIZE; } -} \ No newline at end of file + } + + /** + * Make sure we allocate a buffer sized not bigger than 2048, not higher than what is actually + * needed, and at least one. + * + * @param lengthHint the expected size of the full value + * @return the buffer size + */ + private static int getSuggestedBufferSize(final int lengthHint) { + return Math.max(1, Math.min(lengthHint, BUFFER_SIZE)); + } +} diff --git a/src/main/java/com/sondertara/joya/core/jdbc/StatementCallback.java b/src/main/java/com/sondertara/joya/core/jdbc/StatementCallback.java index d388ba0..3fd2ce9 100644 --- a/src/main/java/com/sondertara/joya/core/jdbc/StatementCallback.java +++ b/src/main/java/com/sondertara/joya/core/jdbc/StatementCallback.java @@ -5,21 +5,19 @@ import java.sql.SQLException; import java.sql.Statement; - /** * @author SonderTara */ @FunctionalInterface public interface StatementCallback { - /** - * in Statement - * - * @param stmt sql Statement - * @return result - * @throws SQLException e - */ - @Nullable - T doInStatement(Statement stmt) throws SQLException; - + /** + * in Statement + * + * @param stmt sql Statement + * @return result + * @throws SQLException e + */ + @Nullable + T doInStatement(Statement stmt) throws SQLException; } diff --git a/src/main/java/com/sondertara/joya/core/jdbc/mapper/BeanRowMapper.java b/src/main/java/com/sondertara/joya/core/jdbc/mapper/BeanRowMapper.java index 3cb645c..544a671 100644 --- a/src/main/java/com/sondertara/joya/core/jdbc/mapper/BeanRowMapper.java +++ b/src/main/java/com/sondertara/joya/core/jdbc/mapper/BeanRowMapper.java @@ -17,49 +17,50 @@ * @author huangxiaohu */ public class BeanRowMapper implements RowMapper { - private final Class type; + private final Class type; - public BeanRowMapper(Class type) { - this.type = type; - } + public BeanRowMapper(Class type) { + this.type = type; + } - @Override - public T map(Row row) { - try { - int count = row.getColumnCount(); - T bean = type.getDeclaredConstructor().newInstance(); - TableEntity tableEntity = null; - if (type.isAnnotationPresent(Table.class) || type.isAnnotationPresent(Entity.class)) { - tableEntity = TableClassCache.getInstance().getTable(bean, false); - } - for (int i = 1; i <= count; i++) { - String propertyName; - if (null != tableEntity) { - propertyName = tableEntity.getRelation().get(row.getColumnLabel(i).toLowerCase()); - } else { - propertyName = StringUtils.toCamelCase(row.getColumnLabel(i)); - } - //the jdk bug,don`t remove the String convert. - PropertyDescriptor pd = new PropertyDescriptor((String) propertyName, type); - Class propertyType = pd.getPropertyType(); - Object value; - if (Number.class.isAssignableFrom(propertyType)) { - value = propertyType.getConstructor(String.class).newInstance(row.getObject(i).toString()); - } else if (propertyType.equals(Boolean.class) || propertyType.equals(boolean.class)) { - value = row.getBoolean(i); - } else if (Date.class.equals(propertyType)) { - value = row.getDate(i); - } else { - value = row.getObject(i); - } - Method setter = pd.getWriteMethod(); - if (null != setter) { - setter.invoke(bean, value); - } - } - return bean; - } catch (Exception e) { - throw new RuntimeException(e.getMessage(), e); + @Override + public T map(Row row) { + try { + int count = row.getColumnCount(); + T bean = type.getDeclaredConstructor().newInstance(); + TableEntity tableEntity = null; + if (type.isAnnotationPresent(Table.class) || type.isAnnotationPresent(Entity.class)) { + tableEntity = TableClassCache.getInstance().getTable(bean, false); + } + for (int i = 1; i <= count; i++) { + String propertyName; + if (null != tableEntity) { + propertyName = tableEntity.getRelation().get(row.getColumnLabel(i).toLowerCase()); + } else { + propertyName = StringUtils.toCamelCase(row.getColumnLabel(i)); + } + // the jdk bug,don`t remove the String convert. + PropertyDescriptor pd = new PropertyDescriptor((String) propertyName, type); + Class propertyType = pd.getPropertyType(); + Object value; + if (Number.class.isAssignableFrom(propertyType)) { + value = + propertyType.getConstructor(String.class).newInstance(row.getObject(i).toString()); + } else if (propertyType.equals(Boolean.class) || propertyType.equals(boolean.class)) { + value = row.getBoolean(i); + } else if (Date.class.equals(propertyType)) { + value = row.getDate(i); + } else { + value = row.getObject(i); + } + Method setter = pd.getWriteMethod(); + if (null != setter) { + setter.invoke(bean, value); } + } + return bean; + } catch (Exception e) { + throw new RuntimeException(e.getMessage(), e); } + } } diff --git a/src/main/java/com/sondertara/joya/core/jdbc/mapper/ListRecordMapper.java b/src/main/java/com/sondertara/joya/core/jdbc/mapper/ListRecordMapper.java index 3f95030..4aa845e 100644 --- a/src/main/java/com/sondertara/joya/core/jdbc/mapper/ListRecordMapper.java +++ b/src/main/java/com/sondertara/joya/core/jdbc/mapper/ListRecordMapper.java @@ -11,18 +11,18 @@ * @author huangxiaohu */ public class ListRecordMapper implements RecordMapper> { - private final RowMapper rowMapper; + private final RowMapper rowMapper; - public ListRecordMapper(RowMapper rowMapper) { - this.rowMapper = rowMapper; - } + public ListRecordMapper(RowMapper rowMapper) { + this.rowMapper = rowMapper; + } - @Override - public List map(Record record) { - List result = new ArrayList<>(); - while (record.next()) { - result.add(rowMapper.map(record.getCurrentRow())); - } - return result; + @Override + public List map(Record record) { + List result = new ArrayList<>(); + while (record.next()) { + result.add(rowMapper.map(record.getCurrentRow())); } + return result; + } } diff --git a/src/main/java/com/sondertara/joya/core/jdbc/mapper/MapRowMapper.java b/src/main/java/com/sondertara/joya/core/jdbc/mapper/MapRowMapper.java index 226fa31..aac7b78 100644 --- a/src/main/java/com/sondertara/joya/core/jdbc/mapper/MapRowMapper.java +++ b/src/main/java/com/sondertara/joya/core/jdbc/mapper/MapRowMapper.java @@ -16,22 +16,22 @@ */ @Slf4j public class MapRowMapper implements RowMapper> { - @Override - public Map map(Row row) { - Map map = new LinkedHashMap<>(); - int count = row.getColumnCount(); - for (int i = 1; i <= count; i++) { - String key = row.getColumnLabel(i); - Object value = row.getObject(i); - if (null != value) { - if (SqlDataHelper.isClob(value.getClass())) { - value = SqlDataHelper.extractString((Clob) value); - } else if (value instanceof TIMESTAMP) { - value = SqlDataHelper.extractDate(value); - } - } - map.put(key, value); + @Override + public Map map(Row row) { + Map map = new LinkedHashMap<>(); + int count = row.getColumnCount(); + for (int i = 1; i <= count; i++) { + String key = row.getColumnLabel(i); + Object value = row.getObject(i); + if (null != value) { + if (SqlDataHelper.isClob(value.getClass())) { + value = SqlDataHelper.extractString((Clob) value); + } else if (value instanceof TIMESTAMP) { + value = SqlDataHelper.extractDate(value); } - return map; + } + map.put(key, value); } + return map; + } } diff --git a/src/main/java/com/sondertara/joya/core/jdbc/mapper/RecordMapper.java b/src/main/java/com/sondertara/joya/core/jdbc/mapper/RecordMapper.java index e57be1e..85744f2 100644 --- a/src/main/java/com/sondertara/joya/core/jdbc/mapper/RecordMapper.java +++ b/src/main/java/com/sondertara/joya/core/jdbc/mapper/RecordMapper.java @@ -10,11 +10,11 @@ @FunctionalInterface public interface RecordMapper { - /** - * convert the record - * - * @param record the result record - * @return the target object - */ - T map(Record record); + /** + * convert the record + * + * @param record the result record + * @return the target object + */ + T map(Record record); } diff --git a/src/main/java/com/sondertara/joya/core/jdbc/mapper/RowMapper.java b/src/main/java/com/sondertara/joya/core/jdbc/mapper/RowMapper.java index 4cf6595..ec0ea6b 100644 --- a/src/main/java/com/sondertara/joya/core/jdbc/mapper/RowMapper.java +++ b/src/main/java/com/sondertara/joya/core/jdbc/mapper/RowMapper.java @@ -8,5 +8,5 @@ * @author huangxiaohu */ public interface RowMapper { - T map(Row row); + T map(Row row); } diff --git a/src/main/java/com/sondertara/joya/core/jdbc/mapper/SingleColumnRowMapper.java b/src/main/java/com/sondertara/joya/core/jdbc/mapper/SingleColumnRowMapper.java index 3b0d2ad..10541ab 100644 --- a/src/main/java/com/sondertara/joya/core/jdbc/mapper/SingleColumnRowMapper.java +++ b/src/main/java/com/sondertara/joya/core/jdbc/mapper/SingleColumnRowMapper.java @@ -13,28 +13,28 @@ */ @Slf4j public class SingleColumnRowMapper implements RowMapper { - private final Class clazz; + private final Class clazz; - public SingleColumnRowMapper(Class clazz) { - this.clazz = clazz; - } + public SingleColumnRowMapper(Class clazz) { + this.clazz = clazz; + } - @Override - @SuppressWarnings("unchecked") - public T map(Row row) { - try { - if (Number.class.isAssignableFrom(this.clazz)) { - return clazz.getDeclaredConstructor(String.class).newInstance(row.getString(1)); - } else if (this.clazz.equals(String.class)) { - return (T) row.getString(1); - } else if (Date.class.equals(this.clazz)) { - return (T) row.getDate(1); - } else { - return (T) row.getObject(1); - } - } catch (Exception e) { - log.error("get column error.", e); - throw new DbException("Get column error.", e); - } + @Override + @SuppressWarnings("unchecked") + public T map(Row row) { + try { + if (Number.class.isAssignableFrom(this.clazz)) { + return clazz.getDeclaredConstructor(String.class).newInstance(row.getString(1)); + } else if (this.clazz.equals(String.class)) { + return (T) row.getString(1); + } else if (Date.class.equals(this.clazz)) { + return (T) row.getDate(1); + } else { + return (T) row.getObject(1); + } + } catch (Exception e) { + log.error("get column error.", e); + throw new DbException("Get column error.", e); } + } } diff --git a/src/main/java/com/sondertara/joya/core/jdbc/mapper/SingleRowRecordMapper.java b/src/main/java/com/sondertara/joya/core/jdbc/mapper/SingleRowRecordMapper.java index c29b94e..102ebf6 100644 --- a/src/main/java/com/sondertara/joya/core/jdbc/mapper/SingleRowRecordMapper.java +++ b/src/main/java/com/sondertara/joya/core/jdbc/mapper/SingleRowRecordMapper.java @@ -8,17 +8,17 @@ * @author huangxiaohu */ public class SingleRowRecordMapper implements RecordMapper { - private final RowMapper rowMapper; + private final RowMapper rowMapper; - public SingleRowRecordMapper(RowMapper rowMapper) { - this.rowMapper = rowMapper; - } + public SingleRowRecordMapper(RowMapper rowMapper) { + this.rowMapper = rowMapper; + } - @Override - public T map(Record record) { - if (record.next()) { - return rowMapper.map(record.getCurrentRow()); - } - return null; + @Override + public T map(Record record) { + if (record.next()) { + return rowMapper.map(record.getCurrentRow()); } + return null; + } } diff --git a/src/main/java/com/sondertara/joya/core/model/ColumnAlias.java b/src/main/java/com/sondertara/joya/core/model/ColumnAlias.java index 0204a24..32e0b13 100644 --- a/src/main/java/com/sondertara/joya/core/model/ColumnAlias.java +++ b/src/main/java/com/sondertara/joya/core/model/ColumnAlias.java @@ -14,26 +14,14 @@ @Data public class ColumnAlias implements Serializable { - /** - * table name of database - * eg: user - */ - private String tableName; + /** table name of database eg: user */ + private String tableName; - /** - * column name form database which has parsed tto lowercase - * eg: user_name - */ - private String columnName; + /** column name form database which has parsed tto lowercase eg: user_name */ + private String columnName; - /** - * table alias - * eg: t0 - */ - private String tableAlias; - /** - * column alias - * eg: t0.user_name - */ - private String columnAlias; + /** table alias eg: t0 */ + private String tableAlias; + /** column alias eg: t0.user_name */ + private String columnAlias; } diff --git a/src/main/java/com/sondertara/joya/core/model/TableAlias.java b/src/main/java/com/sondertara/joya/core/model/TableAlias.java index 8fa189b..78e445f 100644 --- a/src/main/java/com/sondertara/joya/core/model/TableAlias.java +++ b/src/main/java/com/sondertara/joya/core/model/TableAlias.java @@ -13,16 +13,10 @@ */ @Data public class TableAlias implements Serializable { - /** - * the entity full class name - */ - private String className; - /** - * the table name form database - */ - private String tableName; - /** - * the table alias - */ - private String aliasName; + /** the entity full class name */ + private String className; + /** the table name form database */ + private String tableName; + /** the table alias */ + private String aliasName; } diff --git a/src/main/java/com/sondertara/joya/core/model/TableEntity.java b/src/main/java/com/sondertara/joya/core/model/TableEntity.java index 6a0bd4e..b83a0db 100644 --- a/src/main/java/com/sondertara/joya/core/model/TableEntity.java +++ b/src/main/java/com/sondertara/joya/core/model/TableEntity.java @@ -13,27 +13,18 @@ @Data public class TableEntity implements Serializable { - /** - * the table name - */ - private String tableName; - /** - * primary key name if exist - */ - private String primaryKey; - /** - * the type of primary key - */ - private Class primaryKeyType; - /** - * the row data - * key is the column name - */ - private Map data; - /** - * the relation of column and the field - *

- * key is column name ,value is the field name - */ - private Map relation; + /** the table name */ + private String tableName; + /** primary key name if exist */ + private String primaryKey; + /** the type of primary key */ + private Class primaryKeyType; + /** the row data key is the column name */ + private Map data; + /** + * the relation of column and the field + * + *

key is column name ,value is the field name + */ + private Map relation; } diff --git a/src/main/java/com/sondertara/joya/core/model/TableStruct.java b/src/main/java/com/sondertara/joya/core/model/TableStruct.java index 63ba7c2..31ca33f 100644 --- a/src/main/java/com/sondertara/joya/core/model/TableStruct.java +++ b/src/main/java/com/sondertara/joya/core/model/TableStruct.java @@ -14,15 +14,9 @@ */ @Data public final class TableStruct implements Serializable { - private String tableName; - /** - * entity className - */ - private String className; - /** - * the columns map - * key : the fieldName - * value: the table columnName - */ - private Map fields; + private String tableName; + /** entity className */ + private String className; + /** the columns map key : the fieldName value: the table columnName */ + private Map fields; } diff --git a/src/main/java/com/sondertara/joya/core/query/NativeSqlQuery.java b/src/main/java/com/sondertara/joya/core/query/NativeSqlQuery.java index 4addc55..15e6702 100644 --- a/src/main/java/com/sondertara/joya/core/query/NativeSqlQuery.java +++ b/src/main/java/com/sondertara/joya/core/query/NativeSqlQuery.java @@ -1,65 +1,52 @@ package com.sondertara.joya.core.query; - import com.sondertara.joya.core.builder.SelectBuilder; import com.sondertara.joya.utils.SqlUtils; import java.util.List; - /** * 条件查询构造器 * * @author huangxiaohu */ - public class NativeSqlQuery { - - /** - * 查询语句 - */ - private String sqlStr; - /** - * 占位符对应的参数值 - */ - private List params; - - - private NativeSqlQuery() { - } - - protected NativeSqlQuery(String sqlStr, List params) { - this.sqlStr = sqlStr; - this.params = params; - } - - public static SelectBuilder builder() { - return new NativeSqlQueryBuilder(); - } - - - /** - * 获取格式化sql - * - * @return sql - */ - public String toFormattedSql() { - return SqlUtils.formatSql(this.sqlStr); - - } - - public String toSql() { - return this.sqlStr; - } - - public List getParams() { - return params; - } - - @Override - public String toString() { - return "NativeSqlQuery{" + this.toSql() + "}"; - } - + /** 查询语句 */ + private String sqlStr; + /** 占位符对应的参数值 */ + private List params; + + private NativeSqlQuery() {} + + protected NativeSqlQuery(String sqlStr, List params) { + this.sqlStr = sqlStr; + this.params = params; + } + + public static SelectBuilder builder() { + return new NativeSqlQueryBuilder(); + } + + /** + * 获取格式化sql + * + * @return sql + */ + public String toFormattedSql() { + return SqlUtils.formatSql(this.sqlStr); + } + + public String toSql() { + return this.sqlStr; + } + + public List getParams() { + return params; + } + + @Override + public String toString() { + return "NativeSqlQuery{" + this.toSql() + "}"; + } } diff --git a/src/main/java/com/sondertara/joya/core/query/NativeSqlQueryBuilder.java b/src/main/java/com/sondertara/joya/core/query/NativeSqlQueryBuilder.java index 17a2a82..bcf35bf 100644 --- a/src/main/java/com/sondertara/joya/core/query/NativeSqlQueryBuilder.java +++ b/src/main/java/com/sondertara/joya/core/query/NativeSqlQueryBuilder.java @@ -41,496 +41,639 @@ * @author huangxiaohu */ public class NativeSqlQueryBuilder implements SelectBuilder, FromBuilder, WhereBuilder { - private static final Pattern PARAM_PATTERN = Pattern.compile("\\?\\d{1,2}"); - - private static final String SELECT_ALL = "*"; - private String select = SELECT_ALL; - private String from; - - private WhereCriterion where; - - /** - * 特殊select字段 - */ - private List specificS; - - private String groupBy; - private WhereCriterion having; - private List orderBy; - private JoinCriterion joinCriterion; - /** - * 占位符计数器 ?1 ?2 ?3 - */ - private int counts = 0; - - /** - * 占位符对应的参数值 - */ - private List params; - - public NativeSqlQueryBuilder() { - ThreadLocalUtil.put(JoyaConst.JOYA_SQL, Maps.newLinkedHashMap()); - this.orderBy = new ArrayList<>(); - } - - - /** - * select 要查询的列 格式为[t0.user_name] 或者[t0.usr_name AS userName] - */ - @Override - public FromBuilder select(String... columns) { - StringJoiner sj = new StringJoiner(", "); - for (String column : columns) { - String s = SqlUtils.replaceAs(column); - String columnName = SqlUtils.warpColumn(s); - sj.add(columnName); - } - this.select = sj.toString(); - return this; - } - - /** - * 查询表的全部列,对于联表查询 如果字段名字有重复,只保留前面一个字段,可以配置 {@link NativeSqlQueryBuilder#wrapColumn(String...)} ()}wrapColumn来指定字段别名 - */ - @Override - public FromBuilder select() { - return this; - } - - /** - * 特殊select 字段 搭配select(),指定字段的别名 - * - * @param selectFields 特殊字段 - */ - @Override - public SelectBuilder wrapColumn(String... selectFields) { - this.specificS = Lists.newArrayList(selectFields); - return this; - } - - /** - * 选择一个字段 - * - * @param f1 column - * @param entity - * @return query - */ - @Override - public FromBuilder select(TaraFunction f1) { - this.select = AliasThreadLocalCache.getColumn(f1).getColumnAlias(); - return this; - } - - - /** - * @param f1 column1 - * @param f2 column2 - * @param entity1 - * @param entity2 - * @return query - */ - @Override - public FromBuilder select(TaraFunction f1, TaraFunction f2) { - StringJoiner sj = new StringJoiner(", "); - this.select = sj.add(AliasThreadLocalCache.getColumn(f1).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f2).getColumnAlias()).toString(); - return this; - } - - @Override - public FromBuilder select(TaraFunction f1, TaraFunction f2, TaraFunction f3) { - StringJoiner sj = new StringJoiner(", "); - this.select = sj.add(AliasThreadLocalCache.getColumn(f1).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f2).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f3).getColumnAlias()).toString(); - return this; - } - - @Override - public FromBuilder select(TaraFunction f1, TaraFunction f2, TaraFunction f3, TaraFunction f4) { - StringJoiner sj = new StringJoiner(", "); - this.select = sj.add(AliasThreadLocalCache.getColumn(f1).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f2).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f3).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f4).getColumnAlias()).toString(); - return this; - } - - @Override - public FromBuilder select(TaraFunction f1, TaraFunction f2, TaraFunction f3, TaraFunction f4, TaraFunction f5) { - StringJoiner sj = new StringJoiner(", "); - this.select = sj.add(AliasThreadLocalCache.getColumn(f1).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f2).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f3).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f4).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f5).getColumnAlias()).toString(); - return this; - } - - @Override - public FromBuilder select(TaraFunction f1, TaraFunction f2, TaraFunction f3, TaraFunction f4, TaraFunction f5, TaraFunction f6) { - StringJoiner sj = new StringJoiner(", "); - this.select = sj.add(AliasThreadLocalCache.getColumn(f1).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f2).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f3).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f4).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f5).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f6).getColumnAlias()).toString(); - return this; - } - - @Override - public FromBuilder select(TaraFunction f1, TaraFunction f2, TaraFunction f3, TaraFunction f4, TaraFunction f5, TaraFunction f6, TaraFunction f7) { - StringJoiner sj = new StringJoiner(", "); - this.select = sj.add(AliasThreadLocalCache.getColumn(f1).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f2).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f3).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f4).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f5).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f6).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f7).getColumnAlias()).toString(); - return this; - } - - @Override - public FromBuilder select(TaraFunction f1, TaraFunction f2, TaraFunction f3, TaraFunction f4, TaraFunction f5, TaraFunction f6, TaraFunction f7, TaraFunction f8) { - StringJoiner sj = new StringJoiner(", "); - this.select = sj.add(AliasThreadLocalCache.getColumn(f1).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f2).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f3).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f4).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f5).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f6).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f7).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f8).getColumnAlias()).toString(); - return this; - } - - @Override - public FromBuilder select(TaraFunction f1, TaraFunction f2, TaraFunction f3, TaraFunction f4, TaraFunction f5, TaraFunction f6, TaraFunction f7, TaraFunction f8, TaraFunction f9) { - StringJoiner sj = new StringJoiner(", "); - this.select = sj.add(AliasThreadLocalCache.getColumn(f1).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f2).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f3).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f4).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f5).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f6).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f7).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f8).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f9).getColumnAlias()).toString(); - return this; - } - - @Override - public FromBuilder select(TaraFunction f1, TaraFunction f2, TaraFunction f3, TaraFunction f4, TaraFunction f5, TaraFunction f6, TaraFunction f7, TaraFunction f8, TaraFunction f9, TaraFunction f10) { - StringJoiner sj = new StringJoiner(", "); - this.select = sj.add(AliasThreadLocalCache.getColumn(f1).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f2).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f3).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f4).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f5).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f6).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f7).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f8).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f9).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f10).getColumnAlias()).toString(); - return this; - } - - @Override - public FromBuilder select(TaraFunction f1, TaraFunction f2, TaraFunction f3, TaraFunction f4, TaraFunction f5, TaraFunction f6, TaraFunction f7, TaraFunction f8, TaraFunction f9, TaraFunction f10, TaraFunction f11) { - StringJoiner sj = new StringJoiner(", "); - this.select = sj.add(AliasThreadLocalCache.getColumn(f1).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f2).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f3).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f4).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f5).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f6).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f7).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f8).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f9).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f10).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f11).getColumnAlias()).toString(); - return this; - } - - @Override - public FromBuilder select(TaraFunction f1, TaraFunction f2, TaraFunction f3, TaraFunction f4, TaraFunction f5, TaraFunction f6, TaraFunction f7, TaraFunction f8, TaraFunction f9, TaraFunction f10, TaraFunction f11, TaraFunction f12) { - StringJoiner sj = new StringJoiner(", "); - this.select = sj.add(AliasThreadLocalCache.getColumn(f1).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f2).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f3).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f4).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f5).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f6).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f7).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f8).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f9).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f10).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f11).getColumnAlias()).add(AliasThreadLocalCache.getColumn(f12).getColumnAlias()).toString(); - return this; - } - - /** - * lambda select 同样冲突字段需要调用specificS() - * - * @param func select field - * @return query - */ - @Override - public FromBuilder select(UnaryOperator func) { - SelectCriterion selectFields = func.apply(new SelectCriterion()); - this.select = selectFields.getSelectFields(); - return this; - } - - /** - * 字符串格式的from语句 - * from 要查询的表以及关联表 - */ - @Override - public WhereBuilder from(String... tables) { - StringJoiner sj = new StringJoiner(", "); - //1.单表 - for (String table : tables) { - String[] split = table.split(","); - for (String s1 : split) { - s1 = s1.trim(); - if (s1.contains("join")) { - throw new TaraException("Table join is not allowed here,please use [from(Class... clazz)] or [from(UnaryOperator func)]."); - } - //有别名的情况 - if (s1.contains(" ") || StringUtils.containsIgnoreCase(s1, "AS")) { - throw new TaraException("The table alias name will generate by default,so don`t allocate the alias"); - } - sj.add(s1); - AliasThreadLocalCache.generateTableAlias(s1); - } - } - this.from = sj.toString(); - return this; - } - - /** - * 根据class获取表,别名为表的顺序t0,t1,t2,t2 - * - * @param clazz form entity class - * @return query - */ - @Override - public WhereBuilder from(Class... clazz) { - for (Class aClass : clazz) { - //表别名 - AliasThreadLocalCache.generateTableAlias(aClass); - } - return this; - } - - /** - * 根据class获取表,别名为表的顺序t0,t1,t2,t2 - * - * @param func join param - * @return query - */ - @Override - public WhereBuilder from(UnaryOperator func) { - - this.joinCriterion = func.apply(new JoinCriterion()); - return this; - } - - /** - * where - * 使用方式: nativeSql.where(w -> w.eq().ne().in()) - */ - @Override - public ExtPartBuilder where(UnaryOperator func) { - // 条件之间 用 and 连接 - this.where = func.apply(new WhereCriterion(WhereCriterion.Operator.AND)); - return this; - } - - - /** - * where - * 使用方式: nativeSql.where(w -> w.eq().ne().in()) - * - * @param func 条件 - * @param linkOr 是否为or查询 默认为and - */ - @Override - public ExtPartBuilder where(UnaryOperator func, boolean linkOr) { - // 条件之间 用 or 连接 - if (linkOr) { - this.where = func.apply(new WhereCriterion(WhereCriterion.Operator.OR)); - } else { - this.where = func.apply(new WhereCriterion(WhereCriterion.Operator.AND)); + private static final Pattern PARAM_PATTERN = Pattern.compile("\\?\\d{1,2}"); + + private static final String SELECT_ALL = "*"; + private String select = SELECT_ALL; + private String from; + + private WhereCriterion where; + + /** 特殊select字段 */ + private List specificS; + + private String groupBy; + private WhereCriterion having; + private List orderBy; + private JoinCriterion joinCriterion; + /** 占位符计数器 ?1 ?2 ?3 */ + private int counts = 0; + + /** 占位符对应的参数值 */ + private List params; + + public NativeSqlQueryBuilder() { + ThreadLocalUtil.put(JoyaConst.JOYA_SQL, Maps.newLinkedHashMap()); + this.orderBy = new ArrayList<>(); + } + + /** select 要查询的列 格式为[t0.user_name] 或者[t0.usr_name AS userName] */ + @Override + public FromBuilder select(String... columns) { + StringJoiner sj = new StringJoiner(", "); + for (String column : columns) { + String s = SqlUtils.replaceAs(column); + String columnName = SqlUtils.warpColumn(s); + sj.add(columnName); + } + this.select = sj.toString(); + return this; + } + + /** + * 查询表的全部列,对于联表查询 如果字段名字有重复,只保留前面一个字段,可以配置 {@link NativeSqlQueryBuilder#wrapColumn(String...)} + * ()}wrapColumn来指定字段别名 + */ + @Override + public FromBuilder select() { + return this; + } + + /** + * 特殊select 字段 搭配select(),指定字段的别名 + * + * @param selectFields 特殊字段 + */ + @Override + public SelectBuilder wrapColumn(String... selectFields) { + this.specificS = Lists.newArrayList(selectFields); + return this; + } + + /** + * 选择一个字段 + * + * @param f1 column + * @param entity + * @return query + */ + @Override + public FromBuilder select(TaraFunction f1) { + this.select = AliasThreadLocalCache.getColumn(f1).getColumnAlias(); + return this; + } + + /** + * @param f1 column1 + * @param f2 column2 + * @param entity1 + * @param entity2 + * @return query + */ + @Override + public FromBuilder select(TaraFunction f1, TaraFunction f2) { + StringJoiner sj = new StringJoiner(", "); + this.select = + sj.add(AliasThreadLocalCache.getColumn(f1).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f2).getColumnAlias()) + .toString(); + return this; + } + + @Override + public FromBuilder select( + TaraFunction f1, TaraFunction f2, TaraFunction f3) { + StringJoiner sj = new StringJoiner(", "); + this.select = + sj.add(AliasThreadLocalCache.getColumn(f1).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f2).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f3).getColumnAlias()) + .toString(); + return this; + } + + @Override + public FromBuilder select( + TaraFunction f1, + TaraFunction f2, + TaraFunction f3, + TaraFunction f4) { + StringJoiner sj = new StringJoiner(", "); + this.select = + sj.add(AliasThreadLocalCache.getColumn(f1).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f2).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f3).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f4).getColumnAlias()) + .toString(); + return this; + } + + @Override + public FromBuilder select( + TaraFunction f1, + TaraFunction f2, + TaraFunction f3, + TaraFunction f4, + TaraFunction f5) { + StringJoiner sj = new StringJoiner(", "); + this.select = + sj.add(AliasThreadLocalCache.getColumn(f1).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f2).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f3).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f4).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f5).getColumnAlias()) + .toString(); + return this; + } + + @Override + public FromBuilder select( + TaraFunction f1, + TaraFunction f2, + TaraFunction f3, + TaraFunction f4, + TaraFunction f5, + TaraFunction f6) { + StringJoiner sj = new StringJoiner(", "); + this.select = + sj.add(AliasThreadLocalCache.getColumn(f1).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f2).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f3).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f4).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f5).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f6).getColumnAlias()) + .toString(); + return this; + } + + @Override + public FromBuilder select( + TaraFunction f1, + TaraFunction f2, + TaraFunction f3, + TaraFunction f4, + TaraFunction f5, + TaraFunction f6, + TaraFunction f7) { + StringJoiner sj = new StringJoiner(", "); + this.select = + sj.add(AliasThreadLocalCache.getColumn(f1).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f2).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f3).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f4).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f5).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f6).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f7).getColumnAlias()) + .toString(); + return this; + } + + @Override + public FromBuilder select( + TaraFunction f1, + TaraFunction f2, + TaraFunction f3, + TaraFunction f4, + TaraFunction f5, + TaraFunction f6, + TaraFunction f7, + TaraFunction f8) { + StringJoiner sj = new StringJoiner(", "); + this.select = + sj.add(AliasThreadLocalCache.getColumn(f1).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f2).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f3).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f4).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f5).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f6).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f7).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f8).getColumnAlias()) + .toString(); + return this; + } + + @Override + public FromBuilder select( + TaraFunction f1, + TaraFunction f2, + TaraFunction f3, + TaraFunction f4, + TaraFunction f5, + TaraFunction f6, + TaraFunction f7, + TaraFunction f8, + TaraFunction f9) { + StringJoiner sj = new StringJoiner(", "); + this.select = + sj.add(AliasThreadLocalCache.getColumn(f1).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f2).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f3).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f4).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f5).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f6).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f7).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f8).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f9).getColumnAlias()) + .toString(); + return this; + } + + @Override + public FromBuilder select( + TaraFunction f1, + TaraFunction f2, + TaraFunction f3, + TaraFunction f4, + TaraFunction f5, + TaraFunction f6, + TaraFunction f7, + TaraFunction f8, + TaraFunction f9, + TaraFunction f10) { + StringJoiner sj = new StringJoiner(", "); + this.select = + sj.add(AliasThreadLocalCache.getColumn(f1).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f2).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f3).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f4).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f5).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f6).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f7).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f8).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f9).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f10).getColumnAlias()) + .toString(); + return this; + } + + @Override + public FromBuilder select( + TaraFunction f1, + TaraFunction f2, + TaraFunction f3, + TaraFunction f4, + TaraFunction f5, + TaraFunction f6, + TaraFunction f7, + TaraFunction f8, + TaraFunction f9, + TaraFunction f10, + TaraFunction f11) { + StringJoiner sj = new StringJoiner(", "); + this.select = + sj.add(AliasThreadLocalCache.getColumn(f1).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f2).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f3).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f4).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f5).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f6).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f7).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f8).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f9).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f10).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f11).getColumnAlias()) + .toString(); + return this; + } + + @Override + public FromBuilder select( + TaraFunction f1, + TaraFunction f2, + TaraFunction f3, + TaraFunction f4, + TaraFunction f5, + TaraFunction f6, + TaraFunction f7, + TaraFunction f8, + TaraFunction f9, + TaraFunction f10, + TaraFunction f11, + TaraFunction f12) { + StringJoiner sj = new StringJoiner(", "); + this.select = + sj.add(AliasThreadLocalCache.getColumn(f1).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f2).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f3).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f4).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f5).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f6).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f7).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f8).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f9).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f10).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f11).getColumnAlias()) + .add(AliasThreadLocalCache.getColumn(f12).getColumnAlias()) + .toString(); + return this; + } + + /** + * lambda select 同样冲突字段需要调用specificS() + * + * @param func select field + * @return query + */ + @Override + public FromBuilder select(UnaryOperator func) { + SelectCriterion selectFields = func.apply(new SelectCriterion()); + this.select = selectFields.getSelectFields(); + return this; + } + + /** 字符串格式的from语句 from 要查询的表以及关联表 */ + @Override + public WhereBuilder from(String... tables) { + StringJoiner sj = new StringJoiner(", "); + // 1.单表 + for (String table : tables) { + String[] split = table.split(","); + for (String s1 : split) { + s1 = s1.trim(); + if (s1.contains("join")) { + throw new TaraException( + "Table join is not allowed here,please use [from(Class... clazz)] or [from(UnaryOperator func)]."); } - return this; - } - - - /** - * groupBy - */ - @Override - public ExtPartBuilder groupBy(String groupBySegment) { - this.groupBy = groupBySegment; - return this; - } - - /** - * having - * 使用方式: nativeSql.having(h -> h.eq().ne().in()) - */ - @Override - public ExtPartBuilder having(UnaryOperator func) { - // 条件之间 用 and 连接 - this.having = func.apply(new WhereCriterion(WhereCriterion.Operator.AND)); - return this; - } - - - /** - * orderBy - * 排序参数如果是前端传进来,用QueryRequest接收的 ===> nativeSql.orderBy( queryRequest.getOrderBy(表别名) ) - * 手写逻辑指定排序字段 ==> nativeSql.orderBy("su.age asc") - */ - @Override - public ExtPartBuilder orderBy(TaraFunction fn, OrderParam.OrderBy orderBy) { - String column = AliasThreadLocalCache.getColumn(fn).getColumnAlias(); - this.orderBy.add(StringFormatter.format("{} {}", column, orderBy.toString())); - - return this; - } - - /** - * orderBy - * 排序参数如果是前端传进来,用QueryRequest接收的 ===> nativeSql.orderBy( queryRequest.getOrderBy(表别名) ) - * 手写逻辑指定排序字段 ==> nativeSql.orderBy("su.age asc") - */ - @Override - public ExtPartBuilder orderBy(String... orderBySegment) { - if (null != orderBySegment && orderBySegment.length > 0) { - if (orderBy == null) { - // 多次调用此方法,用逗号拼接 ==> su.age asc,so.create_time desc - orderBy = new ArrayList<>(); - } - this.orderBy.addAll(Arrays.asList(orderBySegment)); - } - return this; - } - - private void buildJoin() { - if (StringUtils.isBlank(this.from) && null != joinCriterion) { - NodeList nodeList = joinCriterion.getSegments(); - List join = joinCriterion.getJoin(); - if ((nodeList.getSize() / join.size()) != JoyaConst.TWO_QUERY_COUNT) { - throw new TaraException("The join part is incorrect!"); - } - StringJoiner sb = new StringJoiner(" "); - if (!nodeList.isEmpty()) { - - ColumnAlias first = nodeList.getFirst(); - ColumnAlias second = nodeList.get(1); - - sb.add(first.getTableName()).add("AS").add(first.getTableAlias()); - sb.add(join.get(0)); - sb.add(second.getTableName()).add("AS").add(second.getTableAlias()); - sb.add("ON"); - sb.add(first.getColumnAlias()).add("=").add(second.getColumnAlias()); - if (nodeList.getSize() > JoyaConst.TWO_QUERY_COUNT) { - ColumnAlias third = nodeList.get(2); - ColumnAlias forth = nodeList.get(3); - - if (forth.getTableName().equals(first.getTableName()) || forth.getTableName().equals(second.getTableName())) { - ColumnAlias temp = forth; - forth = third; - third = temp; - } - sb.add(join.get(1)); - sb.add(forth.getTableName()).add("AS").add(forth.getTableAlias()); - sb.add("ON"); - sb.add(third.getColumnAlias()).add("=").add(forth.getColumnAlias()); - } - this.from = sb.toString(); - } - } - } - - /** - * order By - */ - private void buildOrderBy(StringJoiner sj) { - if (CollectionUtils.isEmpty(this.orderBy)) { - return; - + // 有别名的情况 + if (s1.contains(" ") || StringUtils.containsIgnoreCase(s1, "AS")) { + throw new TaraException( + "The table alias name will generate by default,so don`t allocate the alias"); } - StringJoiner sjOrderBy = new StringJoiner(", "); - for (String segment : this.orderBy) { - String[] split = segment.split("(\\s+)"); - String column = split[0]; - String orderByType = split[1]; - - String columnName = AliasThreadLocalCache.getColumnName(column); - sjOrderBy.add(StringFormatter.format("{} {}", columnName, orderByType)); + sj.add(s1); + AliasThreadLocalCache.generateTableAlias(s1); + } + } + this.from = sj.toString(); + return this; + } + + /** + * 根据class获取表,别名为表的顺序t0,t1,t2,t2 + * + * @param clazz form entity class + * @return query + */ + @Override + public WhereBuilder from(Class... clazz) { + for (Class aClass : clazz) { + // 表别名 + AliasThreadLocalCache.generateTableAlias(aClass); + } + return this; + } + + /** + * 根据class获取表,别名为表的顺序t0,t1,t2,t2 + * + * @param func join param + * @return query + */ + @Override + public WhereBuilder from(UnaryOperator func) { + + this.joinCriterion = func.apply(new JoinCriterion()); + return this; + } + + /** where 使用方式: nativeSql.where(w -> w.eq().ne().in()) */ + @Override + public ExtPartBuilder where(UnaryOperator func) { + // 条件之间 用 and 连接 + this.where = func.apply(new WhereCriterion(WhereCriterion.Operator.AND)); + return this; + } + + /** + * where 使用方式: nativeSql.where(w -> w.eq().ne().in()) + * + * @param func 条件 + * @param linkOr 是否为or查询 默认为and + */ + @Override + public ExtPartBuilder where(UnaryOperator func, boolean linkOr) { + // 条件之间 用 or 连接 + if (linkOr) { + this.where = func.apply(new WhereCriterion(WhereCriterion.Operator.OR)); + } else { + this.where = func.apply(new WhereCriterion(WhereCriterion.Operator.AND)); + } + return this; + } + + /** groupBy */ + @Override + public ExtPartBuilder groupBy(String groupBySegment) { + this.groupBy = groupBySegment; + return this; + } + + /** having 使用方式: nativeSql.having(h -> h.eq().ne().in()) */ + @Override + public ExtPartBuilder having(UnaryOperator func) { + // 条件之间 用 and 连接 + this.having = func.apply(new WhereCriterion(WhereCriterion.Operator.AND)); + return this; + } + + /** + * orderBy 排序参数如果是前端传进来,用QueryRequest接收的 ===> nativeSql.orderBy( queryRequest.getOrderBy(表别名) ) + * 手写逻辑指定排序字段 ==> nativeSql.orderBy("su.age asc") + */ + @Override + public ExtPartBuilder orderBy(TaraFunction fn, OrderParam.OrderBy orderBy) { + String column = AliasThreadLocalCache.getColumn(fn).getColumnAlias(); + this.orderBy.add(StringFormatter.format("{} {}", column, orderBy.toString())); + + return this; + } + + /** + * orderBy 排序参数如果是前端传进来,用QueryRequest接收的 ===> nativeSql.orderBy( queryRequest.getOrderBy(表别名) ) + * 手写逻辑指定排序字段 ==> nativeSql.orderBy("su.age asc") + */ + @Override + public ExtPartBuilder orderBy(String... orderBySegment) { + if (null != orderBySegment && orderBySegment.length > 0) { + if (orderBy == null) { + // 多次调用此方法,用逗号拼接 ==> su.age asc,so.create_time desc + orderBy = new ArrayList<>(); + } + this.orderBy.addAll(Arrays.asList(orderBySegment)); + } + return this; + } + + private void buildJoin() { + if (StringUtils.isBlank(this.from) && null != joinCriterion) { + NodeList nodeList = joinCriterion.getSegments(); + List join = joinCriterion.getJoin(); + if ((nodeList.getSize() / join.size()) != JoyaConst.TWO_QUERY_COUNT) { + throw new TaraException("The join part is incorrect!"); + } + StringJoiner sb = new StringJoiner(" "); + if (!nodeList.isEmpty()) { + + ColumnAlias first = nodeList.getFirst(); + ColumnAlias second = nodeList.get(1); + + sb.add(first.getTableName()).add("AS").add(first.getTableAlias()); + sb.add(join.get(0)); + sb.add(second.getTableName()).add("AS").add(second.getTableAlias()); + sb.add("ON"); + sb.add(first.getColumnAlias()).add("=").add(second.getColumnAlias()); + if (nodeList.getSize() > JoyaConst.TWO_QUERY_COUNT) { + ColumnAlias third = nodeList.get(2); + ColumnAlias forth = nodeList.get(3); + + if (forth.getTableName().equals(first.getTableName()) + || forth.getTableName().equals(second.getTableName())) { + ColumnAlias temp = forth; + forth = third; + third = temp; + } + sb.add(join.get(1)); + sb.add(forth.getTableName()).add("AS").add(forth.getTableAlias()); + sb.add("ON"); + sb.add(third.getColumnAlias()).add("=").add(forth.getColumnAlias()); } - sj.add(new StringBuilder("ORDER BY ").append(sjOrderBy)); - } - - private void buildSelect(StringJoiner sj, List tables) { - if (SELECT_ALL.equals(select)) { - Map map = null; - if (null != specificS) { - map = specificS.stream().collect(Collectors.toMap(s -> { - String s1 = SqlUtils.warpColumn(s); - int index = s1.indexOf("AS"); - return StringUtils.trim(s1.substring(0, index)); - }, Function.identity(), (k1, k2) -> k1)); - } - Set columns = new HashSet<>(); - StringJoiner stringJoiner = new StringJoiner(","); - for (TableAlias table : tables) { - TableStruct t = AliasThreadLocalCache.getTable(table.getClassName()); - Map fields = t.getFields(); - for (Map.Entry entity : fields.entrySet()) { - String columnName = entity.getValue(); - String fieldName = entity.getKey(); - if (null != map) { - String s1 = fieldName.equals(StringUtils.toCamelCase(columnName)) ? StringFormatter.format("{}.{}", table.getAliasName(), columnName) : StringFormatter.format("{}.{} AS {} ", table.getAliasName(), columnName, fieldName); - if (map.containsKey(s1)) { - stringJoiner.add(map.get(s1)); - continue; - } - } - if (columns.contains(columnName)) { - continue; - } - columns.add(columnName); - String s = fieldName.equals(StringUtils.toCamelCase(columnName)) ? StringFormatter.format("{}.{}", table.getAliasName(), columnName) : StringFormatter.format("{}.{} AS {}", table.getAliasName(), columnName, fieldName); - stringJoiner.add(s); - } + this.from = sb.toString(); + } + } + } + + /** order By */ + private void buildOrderBy(StringJoiner sj) { + if (CollectionUtils.isEmpty(this.orderBy)) { + return; + } + StringJoiner sjOrderBy = new StringJoiner(", "); + for (String segment : this.orderBy) { + String[] split = segment.split("(\\s+)"); + String column = split[0]; + String orderByType = split[1]; + + String columnName = AliasThreadLocalCache.getColumnName(column); + sjOrderBy.add(StringFormatter.format("{} {}", columnName, orderByType)); + } + sj.add(new StringBuilder("ORDER BY ").append(sjOrderBy)); + } + + private void buildSelect(StringJoiner sj, List tables) { + if (SELECT_ALL.equals(select)) { + Map map = null; + if (null != specificS) { + map = + specificS.stream() + .collect( + Collectors.toMap( + s -> { + String s1 = SqlUtils.warpColumn(s); + int index = s1.indexOf("AS"); + return StringUtils.trim(s1.substring(0, index)); + }, + Function.identity(), + (k1, k2) -> k1)); + } + Set columns = new HashSet<>(); + StringJoiner stringJoiner = new StringJoiner(","); + for (TableAlias table : tables) { + TableStruct t = AliasThreadLocalCache.getTable(table.getClassName()); + Map fields = t.getFields(); + for (Map.Entry entity : fields.entrySet()) { + String columnName = entity.getValue(); + String fieldName = entity.getKey(); + if (null != map) { + String s1 = + fieldName.equals(StringUtils.toCamelCase(columnName)) + ? StringFormatter.format("{}.{}", table.getAliasName(), columnName) + : StringFormatter.format( + "{}.{} AS {} ", table.getAliasName(), columnName, fieldName); + if (map.containsKey(s1)) { + stringJoiner.add(map.get(s1)); + continue; } - this.select = stringJoiner.toString(); + } + if (columns.contains(columnName)) { + continue; + } + columns.add(columnName); + String s = + fieldName.equals(StringUtils.toCamelCase(columnName)) + ? StringFormatter.format("{}.{}", table.getAliasName(), columnName) + : StringFormatter.format( + "{}.{} AS {}", table.getAliasName(), columnName, fieldName); + stringJoiner.add(s); } - sj.add("SELECT " + select); - } - - private void buildForm(StringJoiner sj, List tables) { - //字符串from - if (StringUtils.isNotBlank(from)) { - sj.add("FROM " + from); + } + this.select = stringJoiner.toString(); + } + sj.add("SELECT " + select); + } + + private void buildForm(StringJoiner sj, List tables) { + // 字符串from + if (StringUtils.isNotBlank(from)) { + sj.add("FROM " + from); + } else { + // class from + sj.add("FROM"); + StringJoiner stringJoiner = new StringJoiner(", "); + for (TableAlias table : tables) { + // Oracle not support AS + stringJoiner.add( + StringFormatter.format("{} {}", table.getTableName(), table.getAliasName())); + } + sj.merge(stringJoiner); + } + } + + /** 生成完整的sql */ + private String toSqlStr() { + StringJoiner sj = new StringJoiner(" "); + List tables = AliasThreadLocalCache.getTables(); + // select + buildSelect(sj, tables); + // form + buildForm(sj, tables); + // where + if (where != null) { + String wh = where.getSegments().toString(); + if (wh.length() > 0) { + sj.add("WHERE " + wh); + counts += where.getCounts(); + params = where.getParams(); + } + } + // group by + if (StringUtils.isNotBlank(groupBy)) { + sj.add("GROUP BY " + groupBy); + } + // having + if (having != null) { + String hv = having.getSegments().toString(); + if (hv.length() > 0) { + sj.add("HAVING " + moveCount(hv, counts)); + counts += having.getCounts(); + if (params == null) { + params = having.getParams(); } else { - //class from - sj.add("FROM"); - StringJoiner stringJoiner = new StringJoiner(", "); - for (TableAlias table : tables) { - // Oracle not support AS - stringJoiner.add(StringFormatter.format("{} {}", table.getTableName(), table.getAliasName())); - } - sj.merge(stringJoiner); - } - } - - /** - * 生成完整的sql - */ - private String toSqlStr() { - StringJoiner sj = new StringJoiner(" "); - List tables = AliasThreadLocalCache.getTables(); - //select - buildSelect(sj, tables); - //form - buildForm(sj, tables); - //where - if (where != null) { - String wh = where.getSegments().toString(); - if (wh.length() > 0) { - sj.add("WHERE " + wh); - counts += where.getCounts(); - params = where.getParams(); - } + params.addAll(having.getParams()); } - // group by - if (StringUtils.isNotBlank(groupBy)) { - sj.add("GROUP BY " + groupBy); - } - // having - if (having != null) { - String hv = having.getSegments().toString(); - if (hv.length() > 0) { - sj.add("HAVING " + moveCount(hv, counts)); - counts += having.getCounts(); - if (params == null) { - params = having.getParams(); - } else { - params.addAll(having.getParams()); - } - } - } - // order by - buildOrderBy(sj); - - return sj.toString(); - } - - /** - * build - */ - @Override - public NativeSqlQuery build() { - buildJoin(); - String sqlStr = toSqlStr(); - ThreadLocalUtil.clear(); - return new NativeSqlQuery(sqlStr, this.params); - } - - /** - * 占位符数字调整 - */ - private static String moveCount(String value, int counts) { - StringBuffer sb = new StringBuffer(); - Matcher m = PARAM_PATTERN.matcher(value); - while (m.find()) { - m.appendReplacement(sb, "?" + (Integer.parseInt(m.group().substring(1)) + counts)); - } - m.appendTail(sb); - return sb.toString(); - } - -} \ No newline at end of file + } + } + // order by + buildOrderBy(sj); + + return sj.toString(); + } + + /** build */ + @Override + public NativeSqlQuery build() { + buildJoin(); + String sqlStr = toSqlStr(); + ThreadLocalUtil.clear(); + return new NativeSqlQuery(sqlStr, this.params); + } + + /** 占位符数字调整 */ + private static String moveCount(String value, int counts) { + StringBuffer sb = new StringBuffer(); + Matcher m = PARAM_PATTERN.matcher(value); + while (m.find()) { + m.appendReplacement(sb, "?" + (Integer.parseInt(m.group().substring(1)) + counts)); + } + m.appendTail(sb); + return sb.toString(); + } +} diff --git a/src/main/java/com/sondertara/joya/core/query/criterion/JoinCriterion.java b/src/main/java/com/sondertara/joya/core/query/criterion/JoinCriterion.java index 7f5aa7b..5cf15bb 100644 --- a/src/main/java/com/sondertara/joya/core/query/criterion/JoinCriterion.java +++ b/src/main/java/com/sondertara/joya/core/query/criterion/JoinCriterion.java @@ -1,6 +1,5 @@ package com.sondertara.joya.core.query.criterion; - import com.sondertara.common.exception.TaraException; import com.sondertara.common.function.TaraFunction; import com.sondertara.common.structure.NodeList; @@ -16,137 +15,130 @@ import static com.sondertara.joya.core.constant.JoyaConst.MAX_JOIN_COUNT; /** - * the form part of query with join - *

- * only support join three maximum tables. if the query link more table maybe use more subQuery + * the form part of query with join + * + *

only support join three maximum tables. if the query link more table maybe use more subQuery * * @author huangxiaohu */ public class JoinCriterion { - /** - * from segments - */ - private final NodeList segments; - - /** - * the join type {@link JoinType}; - */ - private final List join; - /** - * the count tables maximum is three - */ - private final Set tableNames; - - - /** - * - */ - public JoinCriterion() { - this.segments = new NodeList<>(); - join = new ArrayList<>(2); - tableNames = new HashSet<>(); - } - - /** - * join - * - * @param left first join part - * @param right second join part - * @param generic of entity - * @param generic - * @return this - */ - public JoinCriterion join(TaraFunction left, TaraFunction right) { - setSegments(JoinType.JOIN, left, right); - return this; - } - - /** - * left join - * - * @param left first join part - * @param right second join part - * @param generic of entity - * @param generic - * @return this - */ - public JoinCriterion leftJoin(TaraFunction left, TaraFunction right) { - setSegments(JoinType.LEFT_JOIN, left, right); - return this; + /** from segments */ + private final NodeList segments; + + /** the join type {@link JoinType}; */ + private final List join; + /** the count tables maximum is three */ + private final Set tableNames; + + /** */ + public JoinCriterion() { + this.segments = new NodeList<>(); + join = new ArrayList<>(2); + tableNames = new HashSet<>(); + } + + /** + * join + * + * @param left first join part + * @param right second join part + * @param generic of entity + * @param generic + * @return this + */ + public JoinCriterion join(TaraFunction left, TaraFunction right) { + setSegments(JoinType.JOIN, left, right); + return this; + } + + /** + * left join + * + * @param left first join part + * @param right second join part + * @param generic of entity + * @param generic + * @return this + */ + public JoinCriterion leftJoin(TaraFunction left, TaraFunction right) { + setSegments(JoinType.LEFT_JOIN, left, right); + return this; + } + + /** + * right join + * + * @param left first join part + * @param right second join part + * @param generic of entity + * @param generic + * @return this + */ + public JoinCriterion rightJoin(TaraFunction left, TaraFunction right) { + setSegments(JoinType.RIGHT_JOIN, left, right); + + return this; + } + + /** + * get the join fields with NodeList which is a list with head node + * + * @return node list for join field + */ + public NodeList getSegments() { + if (tableNames.size() > JoyaConst.MAX_JOIN_TABLE) { + + throw new TaraException("Only support three tables associated"); } - - /** - * right join - * - * @param left first join part - * @param right second join part - * @param generic of entity - * @param generic - * @return this - */ - public JoinCriterion rightJoin(TaraFunction left, TaraFunction right) { - setSegments(JoinType.RIGHT_JOIN, left, right); - - return this; + return segments; + } + + /** + * get join type + * + * @return array of join type + */ + public List getJoin() { + return join; + } + + private void setSegments( + JoinType joinType, TaraFunction left, TaraFunction right) { + if (this.segments.getSize() > MAX_JOIN_COUNT) { + throw new TaraException( + "Only support two join association ," + + "if you use too complicated query why no try to optimize the code."); } - - /** - * get the join fields with NodeList which is a list with head node - * - * @return node list for join field - */ - public NodeList getSegments() { - if (tableNames.size() > JoyaConst.MAX_JOIN_TABLE) { - - throw new TaraException("Only support three tables associated"); - - } - return segments; - } - - /** - * get join type - * - * @return array of join type - */ - public List getJoin() { - return join; - } - - private void setSegments(JoinType joinType, TaraFunction left, TaraFunction right) { - if (this.segments.getSize() > MAX_JOIN_COUNT) { - throw new TaraException("Only support two join association ," + "if you use too complicated query why no try to optimize the code."); - } - final ColumnAlias columnLeft = AliasThreadLocalCache.getColumn(left); - ColumnAlias columnRight = AliasThreadLocalCache.getColumn(right); - setJoinStr(columnLeft, columnRight, joinType); - } - - /** - * set join segments - * - * @param left first part - * @param right second part - * @param joinType join type - */ - private void setJoinStr(ColumnAlias left, ColumnAlias right, JoinType joinType) { - this.segments.addLast(left); - this.segments.addLast(right); - tableNames.add(left.getTableName()); - tableNames.add(right.getTableName()); - this.join.add(joinType.code); - } - - public enum JoinType { - /** - * - */ - JOIN("JOIN"), LEFT_JOIN("LEFT JOIN"), RIGHT_JOIN("RIGHT JOIN"); - private final String code; - - JoinType(String code) { - this.code = code; - } + final ColumnAlias columnLeft = AliasThreadLocalCache.getColumn(left); + ColumnAlias columnRight = AliasThreadLocalCache.getColumn(right); + setJoinStr(columnLeft, columnRight, joinType); + } + + /** + * set join segments + * + * @param left first part + * @param right second part + * @param joinType join type + */ + private void setJoinStr(ColumnAlias left, ColumnAlias right, JoinType joinType) { + this.segments.addLast(left); + this.segments.addLast(right); + tableNames.add(left.getTableName()); + tableNames.add(right.getTableName()); + this.join.add(joinType.code); + } + + public enum JoinType { + /** */ + JOIN("JOIN"), + LEFT_JOIN("LEFT JOIN"), + RIGHT_JOIN("RIGHT JOIN"); + private final String code; + + JoinType(String code) { + this.code = code; } + } } diff --git a/src/main/java/com/sondertara/joya/core/query/criterion/SelectCriterion.java b/src/main/java/com/sondertara/joya/core/query/criterion/SelectCriterion.java index 144597d..5e39cdd 100644 --- a/src/main/java/com/sondertara/joya/core/query/criterion/SelectCriterion.java +++ b/src/main/java/com/sondertara/joya/core/query/criterion/SelectCriterion.java @@ -13,40 +13,35 @@ */ public class SelectCriterion { - /** - * select fields - */ - private final StringJoiner fields; - - /** - * construct - */ - public SelectCriterion() { - this.fields = new StringJoiner(", "); - } - - /** - * add select field - * - * @param fn apply column - * @param generic table entity - * @return this - */ - public SelectCriterion add(TaraFunction fn) { - - String column = AliasThreadLocalCache.getColumn(fn).getColumnAlias(); - fields.add(column); - - return this; - - } - - /** - * get select sql str - * - * @return sql str - */ - public String getSelectFields() { - return this.fields.toString(); - } + /** select fields */ + private final StringJoiner fields; + + /** construct */ + public SelectCriterion() { + this.fields = new StringJoiner(", "); + } + + /** + * add select field + * + * @param fn apply column + * @param generic table entity + * @return this + */ + public SelectCriterion add(TaraFunction fn) { + + String column = AliasThreadLocalCache.getColumn(fn).getColumnAlias(); + fields.add(column); + + return this; + } + + /** + * get select sql str + * + * @return sql str + */ + public String getSelectFields() { + return this.fields.toString(); + } } diff --git a/src/main/java/com/sondertara/joya/core/query/criterion/WhereCriterion.java b/src/main/java/com/sondertara/joya/core/query/criterion/WhereCriterion.java index 4955023..f3a9258 100644 --- a/src/main/java/com/sondertara/joya/core/query/criterion/WhereCriterion.java +++ b/src/main/java/com/sondertara/joya/core/query/criterion/WhereCriterion.java @@ -1,6 +1,5 @@ package com.sondertara.joya.core.query.criterion; - import com.sondertara.common.exception.TaraException; import com.sondertara.common.function.TaraFunction; import com.sondertara.common.util.CollectionUtils; @@ -25,642 +24,669 @@ */ public class WhereCriterion { - - /** - * where condition segments - */ - private final StringJoiner segments; - /** - * params - */ - private final List params; - /** - * 占位符计数器 ?1 ?2 ?3 - */ - private int counts = 1; - /** - * the link type for where segments - */ - private Operator currentOpt; - - /** - * 默认用 and 连接 查询条件 - */ - public WhereCriterion() { - this(Operator.AND); - } - - /** - * 指定查询条件之间是用 and 还是 or 连接 - * - * @param operator Operator.AND/Operator.OR - */ - public WhereCriterion(Operator operator) { - this.currentOpt = operator; - this.segments = new StringJoiner(" " + operator.name() + " "); - this.params = new ArrayList<>(); - } - - public static WhereCriterion get() { - return new WhereCriterion(); - } - - /** - * where 条件 begin - */ - public WhereCriterion eq(String columnName, Object value) { - if (Objects.nonNull(value)) { - segments.add(StringUtils.format("{} = ?{}", AliasThreadLocalCache.getColumnName(columnName), counts++)); - params.add(value); - } - return this; - } - - /** - * where 条件 begin - */ - public WhereCriterion eq(TaraFunction fn, Object value) { - if (Objects.nonNull(value)) { - String tableColumn = AliasThreadLocalCache.getColumn(fn).getColumnAlias(); - segments.add(StringUtils.format("{} = ?{}", tableColumn, counts++)); - params.add(value); - } - return this; - - } - - /** - * where 条件 begin - */ - public WhereCriterion eq(TaraFunction left, TaraFunction right) { - if (null == left || null == right) { - throw new TaraException("The params is required"); - } - String tableColumnL = AliasThreadLocalCache.getColumn(left).getColumnAlias(); - String tableColumnR = AliasThreadLocalCache.getColumn(right).getColumnAlias(); - segments.add(StringUtils.format("{} = {}", tableColumnL, tableColumnR)); - return this; - } - - /** - * 子查询 - */ - public WhereCriterion subQuery(UnaryOperator func) throws RuntimeException { - - Operator operator = Operator.OR.equals(this.currentOpt) ? Operator.AND : Operator.OR; - WhereCriterion apply = func.apply(new WhereCriterion(operator)); - - - StringJoiner joiner = apply.getSegments(); - - if (Objects.isNull(joiner)) { - throw new RuntimeException("sub query is null!"); - } - List params = apply.getParams(); - if (apply.getCounts() < JoyaConst.TWO_QUERY_COUNT) { - throw new RuntimeException("sub query must a least two part!"); - } - String subSql = joiner.toString(); - List all = RegexUtils.findAll("(\\s\\?)[0-9]+", subSql, 0); - - String[] split = subSql.split(" " + operator.name() + " "); - if (CollectionUtils.isNotEmpty(all)) { - for (int i = 0; i < all.size(); i++) { - this.counts += i; - split[i] = split[i].replace(all.get(i), StringFormatter.format(" ?{}", this.counts)); - } - } - subSql = String.join(" " + operator.name() + " ", split); - this.params.addAll(params); - this.segments.add(StringFormatter.format("( {} )", subSql)); - - return this; - } - - /** - * 不等于 - * - * @param columnName column column - * @param value value value - * @return where criterion - */ - public WhereCriterion ne(String columnName, Object value) { - if (Objects.nonNull(value)) { - segments.add(StringUtils.format("{} != ?{}", AliasThreadLocalCache.getColumnName(columnName), counts++)); - params.add(value); - } - return this; - } - - /** - * 小于 - * - * @param fn column 列名 - * @param value value 值 - * @return where criterion - */ - public WhereCriterion lt(TaraFunction fn, Object value) { - if (Objects.nonNull(value)) { - String tableColumn = AliasThreadLocalCache.getColumn(fn).getColumnAlias(); - segments.add(StringUtils.format("{} < ?{}", tableColumn, counts++)); - params.add(value); - } - return this; - } - - /** - * 小于 - * - * @param columnName column 列名 - * @param value value 值 - * @return where criterion - */ - public WhereCriterion lt(String columnName, Object value) { - if (Objects.nonNull(value)) { - segments.add(StringUtils.format("{} < ?{}", AliasThreadLocalCache.getColumnName(columnName), counts++)); - params.add(value); - } - return this; - } - - /** - * 小于等于 - * - * @param fn column 列名 - * @param value value value - * @return where criterion - */ - public WhereCriterion lte(TaraFunction fn, Object value) { - if (Objects.nonNull(value)) { - String tableColumn = AliasThreadLocalCache.getColumn(fn).getColumnAlias(); - segments.add(StringUtils.format("{} <= ?{}", tableColumn, counts++)); - params.add(value); - } - return this; - } - - /** - * 小于等于 - * - * @param columnName column column - * @param value value value - * @return where criterion - */ - public WhereCriterion lte(String columnName, Object value) { - if (Objects.nonNull(value)) { - segments.add(StringUtils.format("{} <= ?{}", AliasThreadLocalCache.getColumnName(columnName), counts++)); - params.add(value); - } - return this; - } - - /** - * 大于 - * - * @param fn column 列名 - * @param value value value - * @return where criterion - */ - public WhereCriterion gt(TaraFunction fn, Object value) { - if (Objects.nonNull(value)) { - String tableColumn = AliasThreadLocalCache.getColumn(fn).getColumnAlias(); - segments.add(StringUtils.format("{} > ?{}", tableColumn, counts++)); - params.add(value); - } - return this; - } - - /** - * 大于 - * - * @param columnName column column - * @param value value value - * @return where criterion - */ - public WhereCriterion gt(String columnName, Object value) { - if (Objects.nonNull(value)) { - segments.add(StringUtils.format("{} > ?{}", AliasThreadLocalCache.getColumnName(columnName), counts++)); - params.add(value); - } - return this; - } - - /** - * 大于等于 - * - * @param fn column - * @param value value - * @return where criterion - */ - public WhereCriterion gte(TaraFunction fn, Object value) { - if (Objects.nonNull(value)) { - String tableColumn = AliasThreadLocalCache.getColumn(fn).getColumnAlias(); - segments.add(StringUtils.format("{} >= ?{}", tableColumn, counts++)); - params.add(value); - } - return this; - } - - /** - * 大于等于 - * - * @param columnName column - * @param value value - * @return where criterion - */ - public WhereCriterion gte(String columnName, Object value) { - if (Objects.nonNull(value)) { - segments.add(StringUtils.format("{} >= ?{}", AliasThreadLocalCache.getColumnName(columnName), counts++)); - params.add(value); - } - return this; - } - - /** - * is null - * - * @param fn column - * @return where criterion - */ - public WhereCriterion isNull(TaraFunction fn) { - String tableColumn = AliasThreadLocalCache.getColumn(fn).getColumnAlias(); - segments.add(tableColumn + " IS NULL"); - return this; - } - - /** - * is null - * - * @param columnName column - * @return where criterion - */ - public WhereCriterion isNull(String columnName) { - segments.add(AliasThreadLocalCache.getColumnName(columnName) + " IS NULL"); - return this; - } - - /** - * is not null - * - * @param fn column - * @return where criterion - */ - public WhereCriterion isNotNull(TaraFunction fn) { - String tableColumn = AliasThreadLocalCache.getColumn(fn).getColumnAlias(); - - segments.add(tableColumn + " IS NOT NULL"); - return this; - } - - /** - * is not null - * - * @param columnName column - * @return where criterion - */ - public WhereCriterion isNotNull(String columnName) { - segments.add(AliasThreadLocalCache.getColumnName(columnName) + " IS NOT NULL"); - return this; - } - - /** - * right like - * - * @param fn column column name - * @param value value filed - * @return where criterion - */ - public WhereCriterion startsWith(TaraFunction fn, Object value) { - if (Objects.nonNull(value)) { - String tableColumn = AliasThreadLocalCache.getColumn(fn).getColumnAlias(); - segments.add(StringUtils.format("{} LIKE ?{}", tableColumn, counts++)); - params.add(value + "%"); - } - return this; - } - - /** - * right like - * - * @param columnName column - * @param value value - * @return where criterion - */ - public WhereCriterion startsWith(String columnName, Object value) { - if (Objects.nonNull(value)) { - AliasThreadLocalCache.getColumnName(columnName); - segments.add(StringUtils.format("{} LIKE ?{}", AliasThreadLocalCache.getColumnName(columnName), counts++)); - params.add(value + "%"); - } - return this; - } - - /** - * like - * - * @param fn column - * @param value value - * @return where criterion - */ - public WhereCriterion contains(TaraFunction fn, Object value) { - if (Objects.nonNull(value)) { - String tableColumn = AliasThreadLocalCache.getColumn(fn).getColumnAlias(); - segments.add(StringUtils.format("{} LIKE ?{}", tableColumn, counts++)); - params.add("%" + value + "%"); - } - return this; - } - - /** - * like - * - * @param columnName column - * @param value value - * @return where criterion - */ - public WhereCriterion contains(String columnName, Object value) { - if (Objects.nonNull(value)) { - segments.add(StringUtils.format("{} LIKE ?{}", AliasThreadLocalCache.getColumnName(columnName), counts++)); - params.add("%" + value + "%"); - } - return this; - } - - /** - * left like - * - * @param fn column - * @param value value - * @return where criterion - */ - public WhereCriterion endsWith(TaraFunction fn, Object value) { - if (Objects.nonNull(value)) { - String tableColumn = AliasThreadLocalCache.getColumn(fn).getColumnAlias(); - segments.add(StringUtils.format("{} LIKE ?{}", tableColumn, counts++)); - params.add("%" + value); - } - return this; - } - - /** - * left like - * - * @param columnName column - * @param value value - * @return where criterion - */ - public WhereCriterion endsWith(String columnName, Object value) { - if (Objects.nonNull(value)) { - segments.add(StringUtils.format("{} LIKE ?{}", AliasThreadLocalCache.getColumnName(columnName), counts++)); - params.add("%" + value); - } - return this; - } - - /** - * not right like - * - * @param fn column - * @param value value - * @return where criterion - */ - public WhereCriterion notStartsWith(TaraFunction fn, Object value) { - if (Objects.nonNull(value)) { - String tableColumn = AliasThreadLocalCache.getColumn(fn).getColumnAlias(); - segments.add(StringUtils.format("{} NOT LIKE ?{}", tableColumn, counts++)); - params.add(value + "%"); - } - return this; - } - - /** - * not right like - * - * @param columnName column - * @param value value - * @return where criterion - */ - public WhereCriterion notStartsWith(String columnName, Object value) { - if (Objects.nonNull(value)) { - segments.add(StringUtils.format("{} NOT LIKE ?{}", AliasThreadLocalCache.getColumnName(columnName), counts++)); - params.add(value + "%"); - } - return this; - } - - /** - * not like - * - * @param fn column - * @param value value - * @return where criterion - */ - public WhereCriterion notContains(TaraFunction fn, Object value) { - if (Objects.nonNull(value)) { - String tableColumn = AliasThreadLocalCache.getColumn(fn).getColumnAlias(); - segments.add(StringUtils.format("{} NOT LIKE ?{}", tableColumn, counts++)); - params.add("%" + value + "%"); - } - return this; - } - - /** - * not like - * - * @param columnName column - * @param value value - * @return where criterion - */ - public WhereCriterion notContains(String columnName, Object value) { - if (Objects.nonNull(value)) { - segments.add(StringUtils.format("{} NOT LIKE ?{}", AliasThreadLocalCache.getColumnName(columnName), counts++)); - params.add("%" + value + "%"); - } - return this; - } - - /** - * not left like - * - * @param columnName column - * @param value value - * @return where criterion - */ - - public WhereCriterion notEndsWith(String columnName, Object value) { - if (Objects.nonNull(value)) { - segments.add(StringUtils.format("{} NOT LIKE ?{}", AliasThreadLocalCache.getColumnName(columnName), counts++)); - params.add("%" + value); - } - return this; - } - - /** - * not left like - * - * @param fn column - * @param value value - * @return where criterion - */ - - public WhereCriterion notEndsWith(TaraFunction fn, Object value) { - if (Objects.nonNull(value)) { - String tableColumn = AliasThreadLocalCache.getColumn(fn).getColumnAlias(); - segments.add(StringUtils.format("{} NOT LIKE ?{}", tableColumn, counts++)); - params.add("%" + value); - } - return this; - } - - /** - * in - * - * @param columnName column - * @param value value - * @return where criterion - */ - public WhereCriterion in(String columnName, Collection value) { - if (Objects.nonNull(value)) { - segments.add(StringUtils.format("{} IN ?{}", AliasThreadLocalCache.getColumnName(columnName), counts++)); - params.add(value); - } - return this; - } - - /** - * in - * - * @param fn column - * @param value value - * @return where criterion - */ - public WhereCriterion in(TaraFunction fn, Collection value) { - if (Objects.nonNull(value)) { - String tableColumn = AliasThreadLocalCache.getColumn(fn).getColumnAlias(); - segments.add(StringUtils.format("{} IN ?{}", tableColumn, counts++)); - params.add(value); - } - return this; - } - - /** - * not in - * - * @param columnName column - * @param value value - * @return where criterion - */ - public WhereCriterion notIn(String columnName, Collection value) { - if (Objects.nonNull(value)) { - segments.add(StringUtils.format("{} NOT IN ?{}", AliasThreadLocalCache.getColumnName(columnName), counts++)); - params.add(value); - } - return this; - } - - /** - * not in - * - * @param fn column - * @param value value - * @return where criterion - */ - public WhereCriterion notIn(TaraFunction fn, Collection value) { - if (Objects.nonNull(value)) { - String tableColumn = AliasThreadLocalCache.getColumn(fn).getColumnAlias(); - segments.add(StringUtils.format("{} NOT IN ?{}", tableColumn, counts++)); - params.add(value); - } - return this; - } - - /** - * between - * - * @param columnName column - * @param values values - * @return where criterion - */ - public WhereCriterion between(String columnName, List values) { - if (CollectionUtils.isNotEmpty(values) && values.size() == JoyaConst.TWO_QUERY_COUNT) { - segments.add(StringUtils.format("{} BETWEEN ?{} AND ?{}", AliasThreadLocalCache.getColumnName(columnName), counts++, counts++)); - params.addAll(values); - } - return this; - } - - /** - * between - * - * @param fn column - * @param values values - * @return where criterion - */ - public WhereCriterion between(TaraFunction fn, List values) { - if (CollectionUtils.isNotEmpty(values) && values.size() == JoyaConst.TWO_QUERY_COUNT) { - String tableColumn = AliasThreadLocalCache.getColumn(fn).getColumnAlias(); - segments.add(StringUtils.format("{} BETWEEN ?{} AND ?{}", tableColumn, counts++, counts++)); - params.addAll(values); - } - return this; - } - - /** - * not between - * - * @param columnName column - * @param values values - * @return where criterion - */ - public WhereCriterion notBetween(String columnName, List values) { - if (CollectionUtils.isNotEmpty(values) && values.size() == JoyaConst.TWO_QUERY_COUNT) { - segments.add(StringUtils.format("{} NOT BETWEEN ?{} AND ?{}", AliasThreadLocalCache.getColumnName(columnName), counts++, counts++)); - params.addAll(values); - } - return this; - } - - /** - * not between - * - * @param fn column - * @param values values - * @return where criterion - */ - public WhereCriterion notBetween(TaraFunction fn, List values) { - if (CollectionUtils.isNotEmpty(values) && values.size() == JoyaConst.TWO_QUERY_COUNT) { - String tableColumn = AliasThreadLocalCache.getColumn(fn).getColumnAlias(); - segments.add(StringUtils.format("{} NOT BETWEEN ?{} AND ?{}", tableColumn, counts++, counts++)); - params.addAll(values); - } - return this; - } - - /** - * 追加到 where条件中自定义sql字符串片段 - */ - public void addCondition(String part) { - this.segments.add(SqlUtils.underlineColumn(part)); - } - - public StringJoiner getSegments() { - return this.segments; - } - - public int getCounts() { - return counts - 1; - } - - public List getParams() { - return params; - } - - public enum Operator { - /** - * - */ - EQ, NE, LT, LTE, GT, GTE, ISNULL, IS_NOT_NULL, ISEMPTY, IS_NOT_EMPTY, LIKE, NOT_LIKE, IN, NOTIN, BETWEEN, NOT_BETWEEN, AND, OR - } - - + /** where condition segments */ + private final StringJoiner segments; + /** params */ + private final List params; + /** 占位符计数器 ?1 ?2 ?3 */ + private int counts = 1; + /** the link type for where segments */ + private final Operator currentOpt; + + /** 默认用 and 连接 查询条件 */ + public WhereCriterion() { + this(Operator.AND); + } + + /** + * 指定查询条件之间是用 and 还是 or 连接 + * + * @param operator Operator.AND/Operator.OR + */ + public WhereCriterion(Operator operator) { + this.currentOpt = operator; + this.segments = new StringJoiner(" " + operator.name() + " "); + this.params = new ArrayList<>(); + } + + public static WhereCriterion get() { + return new WhereCriterion(); + } + + /** where 条件 begin */ + public WhereCriterion eq(String columnName, Object value) { + if (Objects.nonNull(value)) { + segments.add( + StringUtils.format( + "{} = ?{}", AliasThreadLocalCache.getColumnName(columnName), counts++)); + params.add(value); + } + return this; + } + + /** where 条件 begin */ + public WhereCriterion eq(TaraFunction fn, Object value) { + if (Objects.nonNull(value)) { + String tableColumn = AliasThreadLocalCache.getColumn(fn).getColumnAlias(); + segments.add(StringUtils.format("{} = ?{}", tableColumn, counts++)); + params.add(value); + } + return this; + } + + /** where 条件 begin */ + public WhereCriterion eq(TaraFunction left, TaraFunction right) { + if (null == left || null == right) { + throw new TaraException("The params is required"); + } + String tableColumnL = AliasThreadLocalCache.getColumn(left).getColumnAlias(); + String tableColumnR = AliasThreadLocalCache.getColumn(right).getColumnAlias(); + segments.add(StringUtils.format("{} = {}", tableColumnL, tableColumnR)); + return this; + } + + /** 子查询 */ + public WhereCriterion subQuery(UnaryOperator func) throws RuntimeException { + + Operator operator = Operator.OR.equals(this.currentOpt) ? Operator.AND : Operator.OR; + WhereCriterion apply = func.apply(new WhereCriterion(operator)); + + StringJoiner joiner = apply.getSegments(); + + if (Objects.isNull(joiner)) { + throw new RuntimeException("sub query is null!"); + } + List params = apply.getParams(); + if (apply.getCounts() < JoyaConst.TWO_QUERY_COUNT) { + throw new RuntimeException("sub query must a least two part!"); + } + String subSql = joiner.toString(); + List all = RegexUtils.findAll("(\\s\\?)[0-9]+", subSql, 0); + + String[] split = subSql.split(" " + operator.name() + " "); + if (CollectionUtils.isNotEmpty(all)) { + for (int i = 0; i < all.size(); i++) { + this.counts += i; + split[i] = split[i].replace(all.get(i), StringFormatter.format(" ?{}", this.counts)); + } + } + subSql = String.join(" " + operator.name() + " ", split); + this.params.addAll(params); + this.segments.add(StringFormatter.format("( {} )", subSql)); + + return this; + } + + /** + * 不等于 + * + * @param columnName column column + * @param value value value + * @return where criterion + */ + public WhereCriterion ne(String columnName, Object value) { + if (Objects.nonNull(value)) { + segments.add( + StringUtils.format( + "{} != ?{}", AliasThreadLocalCache.getColumnName(columnName), counts++)); + params.add(value); + } + return this; + } + + /** + * 小于 + * + * @param fn column 列名 + * @param value value 值 + * @return where criterion + */ + public WhereCriterion lt(TaraFunction fn, Object value) { + if (Objects.nonNull(value)) { + String tableColumn = AliasThreadLocalCache.getColumn(fn).getColumnAlias(); + segments.add(StringUtils.format("{} < ?{}", tableColumn, counts++)); + params.add(value); + } + return this; + } + + /** + * 小于 + * + * @param columnName column 列名 + * @param value value 值 + * @return where criterion + */ + public WhereCriterion lt(String columnName, Object value) { + if (Objects.nonNull(value)) { + segments.add( + StringUtils.format( + "{} < ?{}", AliasThreadLocalCache.getColumnName(columnName), counts++)); + params.add(value); + } + return this; + } + + /** + * 小于等于 + * + * @param fn column 列名 + * @param value value value + * @return where criterion + */ + public WhereCriterion lte(TaraFunction fn, Object value) { + if (Objects.nonNull(value)) { + String tableColumn = AliasThreadLocalCache.getColumn(fn).getColumnAlias(); + segments.add(StringUtils.format("{} <= ?{}", tableColumn, counts++)); + params.add(value); + } + return this; + } + + /** + * 小于等于 + * + * @param columnName column column + * @param value value value + * @return where criterion + */ + public WhereCriterion lte(String columnName, Object value) { + if (Objects.nonNull(value)) { + segments.add( + StringUtils.format( + "{} <= ?{}", AliasThreadLocalCache.getColumnName(columnName), counts++)); + params.add(value); + } + return this; + } + + /** + * 大于 + * + * @param fn column 列名 + * @param value value value + * @return where criterion + */ + public WhereCriterion gt(TaraFunction fn, Object value) { + if (Objects.nonNull(value)) { + String tableColumn = AliasThreadLocalCache.getColumn(fn).getColumnAlias(); + segments.add(StringUtils.format("{} > ?{}", tableColumn, counts++)); + params.add(value); + } + return this; + } + + /** + * 大于 + * + * @param columnName column column + * @param value value value + * @return where criterion + */ + public WhereCriterion gt(String columnName, Object value) { + if (Objects.nonNull(value)) { + segments.add( + StringUtils.format( + "{} > ?{}", AliasThreadLocalCache.getColumnName(columnName), counts++)); + params.add(value); + } + return this; + } + + /** + * 大于等于 + * + * @param fn column + * @param value value + * @return where criterion + */ + public WhereCriterion gte(TaraFunction fn, Object value) { + if (Objects.nonNull(value)) { + String tableColumn = AliasThreadLocalCache.getColumn(fn).getColumnAlias(); + segments.add(StringUtils.format("{} >= ?{}", tableColumn, counts++)); + params.add(value); + } + return this; + } + + /** + * 大于等于 + * + * @param columnName column + * @param value value + * @return where criterion + */ + public WhereCriterion gte(String columnName, Object value) { + if (Objects.nonNull(value)) { + segments.add( + StringUtils.format( + "{} >= ?{}", AliasThreadLocalCache.getColumnName(columnName), counts++)); + params.add(value); + } + return this; + } + + /** + * is null + * + * @param fn column + * @return where criterion + */ + public WhereCriterion isNull(TaraFunction fn) { + String tableColumn = AliasThreadLocalCache.getColumn(fn).getColumnAlias(); + segments.add(tableColumn + " IS NULL"); + return this; + } + + /** + * is null + * + * @param columnName column + * @return where criterion + */ + public WhereCriterion isNull(String columnName) { + segments.add(AliasThreadLocalCache.getColumnName(columnName) + " IS NULL"); + return this; + } + + /** + * is not null + * + * @param fn column + * @return where criterion + */ + public WhereCriterion isNotNull(TaraFunction fn) { + String tableColumn = AliasThreadLocalCache.getColumn(fn).getColumnAlias(); + + segments.add(tableColumn + " IS NOT NULL"); + return this; + } + + /** + * is not null + * + * @param columnName column + * @return where criterion + */ + public WhereCriterion isNotNull(String columnName) { + segments.add(AliasThreadLocalCache.getColumnName(columnName) + " IS NOT NULL"); + return this; + } + + /** + * right like + * + * @param fn column column name + * @param value value filed + * @return where criterion + */ + public WhereCriterion startsWith(TaraFunction fn, Object value) { + if (Objects.nonNull(value)) { + String tableColumn = AliasThreadLocalCache.getColumn(fn).getColumnAlias(); + segments.add(StringUtils.format("{} LIKE ?{}", tableColumn, counts++)); + params.add(value + "%"); + } + return this; + } + + /** + * right like + * + * @param columnName column + * @param value value + * @return where criterion + */ + public WhereCriterion startsWith(String columnName, Object value) { + if (Objects.nonNull(value)) { + AliasThreadLocalCache.getColumnName(columnName); + segments.add( + StringUtils.format( + "{} LIKE ?{}", AliasThreadLocalCache.getColumnName(columnName), counts++)); + params.add(value + "%"); + } + return this; + } + + /** + * like + * + * @param fn column + * @param value value + * @return where criterion + */ + public WhereCriterion contains(TaraFunction fn, Object value) { + if (Objects.nonNull(value)) { + String tableColumn = AliasThreadLocalCache.getColumn(fn).getColumnAlias(); + segments.add(StringUtils.format("{} LIKE ?{}", tableColumn, counts++)); + params.add("%" + value + "%"); + } + return this; + } + + /** + * like + * + * @param columnName column + * @param value value + * @return where criterion + */ + public WhereCriterion contains(String columnName, Object value) { + if (Objects.nonNull(value)) { + segments.add( + StringUtils.format( + "{} LIKE ?{}", AliasThreadLocalCache.getColumnName(columnName), counts++)); + params.add("%" + value + "%"); + } + return this; + } + + /** + * left like + * + * @param fn column + * @param value value + * @return where criterion + */ + public WhereCriterion endsWith(TaraFunction fn, Object value) { + if (Objects.nonNull(value)) { + String tableColumn = AliasThreadLocalCache.getColumn(fn).getColumnAlias(); + segments.add(StringUtils.format("{} LIKE ?{}", tableColumn, counts++)); + params.add("%" + value); + } + return this; + } + + /** + * left like + * + * @param columnName column + * @param value value + * @return where criterion + */ + public WhereCriterion endsWith(String columnName, Object value) { + if (Objects.nonNull(value)) { + segments.add( + StringUtils.format( + "{} LIKE ?{}", AliasThreadLocalCache.getColumnName(columnName), counts++)); + params.add("%" + value); + } + return this; + } + + /** + * not right like + * + * @param fn column + * @param value value + * @return where criterion + */ + public WhereCriterion notStartsWith(TaraFunction fn, Object value) { + if (Objects.nonNull(value)) { + String tableColumn = AliasThreadLocalCache.getColumn(fn).getColumnAlias(); + segments.add(StringUtils.format("{} NOT LIKE ?{}", tableColumn, counts++)); + params.add(value + "%"); + } + return this; + } + + /** + * not right like + * + * @param columnName column + * @param value value + * @return where criterion + */ + public WhereCriterion notStartsWith(String columnName, Object value) { + if (Objects.nonNull(value)) { + segments.add( + StringUtils.format( + "{} NOT LIKE ?{}", AliasThreadLocalCache.getColumnName(columnName), counts++)); + params.add(value + "%"); + } + return this; + } + + /** + * not like + * + * @param fn column + * @param value value + * @return where criterion + */ + public WhereCriterion notContains(TaraFunction fn, Object value) { + if (Objects.nonNull(value)) { + String tableColumn = AliasThreadLocalCache.getColumn(fn).getColumnAlias(); + segments.add(StringUtils.format("{} NOT LIKE ?{}", tableColumn, counts++)); + params.add("%" + value + "%"); + } + return this; + } + + /** + * not like + * + * @param columnName column + * @param value value + * @return where criterion + */ + public WhereCriterion notContains(String columnName, Object value) { + if (Objects.nonNull(value)) { + segments.add( + StringUtils.format( + "{} NOT LIKE ?{}", AliasThreadLocalCache.getColumnName(columnName), counts++)); + params.add("%" + value + "%"); + } + return this; + } + + /** + * not left like + * + * @param columnName column + * @param value value + * @return where criterion + */ + public WhereCriterion notEndsWith(String columnName, Object value) { + if (Objects.nonNull(value)) { + segments.add( + StringUtils.format( + "{} NOT LIKE ?{}", AliasThreadLocalCache.getColumnName(columnName), counts++)); + params.add("%" + value); + } + return this; + } + + /** + * not left like + * + * @param fn column + * @param value value + * @return where criterion + */ + public WhereCriterion notEndsWith(TaraFunction fn, Object value) { + if (Objects.nonNull(value)) { + String tableColumn = AliasThreadLocalCache.getColumn(fn).getColumnAlias(); + segments.add(StringUtils.format("{} NOT LIKE ?{}", tableColumn, counts++)); + params.add("%" + value); + } + return this; + } + + /** + * in + * + * @param columnName column + * @param value value + * @return where criterion + */ + public WhereCriterion in(String columnName, Collection value) { + if (Objects.nonNull(value)) { + segments.add( + StringUtils.format( + "{} IN ?{}", AliasThreadLocalCache.getColumnName(columnName), counts++)); + params.add(value); + } + return this; + } + + /** + * in + * + * @param fn column + * @param value value + * @return where criterion + */ + public WhereCriterion in(TaraFunction fn, Collection value) { + if (Objects.nonNull(value)) { + String tableColumn = AliasThreadLocalCache.getColumn(fn).getColumnAlias(); + segments.add(StringUtils.format("{} IN ?{}", tableColumn, counts++)); + params.add(value); + } + return this; + } + + /** + * not in + * + * @param columnName column + * @param value value + * @return where criterion + */ + public WhereCriterion notIn(String columnName, Collection value) { + if (Objects.nonNull(value)) { + segments.add( + StringUtils.format( + "{} NOT IN ?{}", AliasThreadLocalCache.getColumnName(columnName), counts++)); + params.add(value); + } + return this; + } + + /** + * not in + * + * @param fn column + * @param value value + * @return where criterion + */ + public WhereCriterion notIn(TaraFunction fn, Collection value) { + if (Objects.nonNull(value)) { + String tableColumn = AliasThreadLocalCache.getColumn(fn).getColumnAlias(); + segments.add(StringUtils.format("{} NOT IN ?{}", tableColumn, counts++)); + params.add(value); + } + return this; + } + + /** + * between + * + * @param columnName column + * @param values values + * @return where criterion + */ + public WhereCriterion between(String columnName, List values) { + if (CollectionUtils.isNotEmpty(values) && values.size() == JoyaConst.TWO_QUERY_COUNT) { + segments.add( + StringUtils.format( + "{} BETWEEN ?{} AND ?{}", + AliasThreadLocalCache.getColumnName(columnName), + counts++, + counts++)); + params.addAll(values); + } + return this; + } + + /** + * between + * + * @param fn column + * @param values values + * @return where criterion + */ + public WhereCriterion between(TaraFunction fn, List values) { + if (CollectionUtils.isNotEmpty(values) && values.size() == JoyaConst.TWO_QUERY_COUNT) { + String tableColumn = AliasThreadLocalCache.getColumn(fn).getColumnAlias(); + segments.add(StringUtils.format("{} BETWEEN ?{} AND ?{}", tableColumn, counts++, counts++)); + params.addAll(values); + } + return this; + } + + /** + * not between + * + * @param columnName column + * @param values values + * @return where criterion + */ + public WhereCriterion notBetween(String columnName, List values) { + if (CollectionUtils.isNotEmpty(values) && values.size() == JoyaConst.TWO_QUERY_COUNT) { + segments.add( + StringUtils.format( + "{} NOT BETWEEN ?{} AND ?{}", + AliasThreadLocalCache.getColumnName(columnName), + counts++, + counts++)); + params.addAll(values); + } + return this; + } + + /** + * not between + * + * @param fn column + * @param values values + * @return where criterion + */ + public WhereCriterion notBetween(TaraFunction fn, List values) { + if (CollectionUtils.isNotEmpty(values) && values.size() == JoyaConst.TWO_QUERY_COUNT) { + String tableColumn = AliasThreadLocalCache.getColumn(fn).getColumnAlias(); + segments.add( + StringUtils.format("{} NOT BETWEEN ?{} AND ?{}", tableColumn, counts++, counts++)); + params.addAll(values); + } + return this; + } + + /** 追加到 where条件中自定义sql字符串片段 */ + public void addCondition(String part) { + this.segments.add(SqlUtils.underlineColumn(part)); + } + + public StringJoiner getSegments() { + return this.segments; + } + + public int getCounts() { + return counts - 1; + } + + public List getParams() { + return params; + } + + public enum Operator { + /** */ + EQ, + NE, + LT, + LTE, + GT, + GTE, + ISNULL, + IS_NOT_NULL, + ISEMPTY, + IS_NOT_EMPTY, + LIKE, + NOT_LIKE, + IN, + NOTIN, + BETWEEN, + NOT_BETWEEN, + AND, + OR + } } diff --git a/src/main/java/com/sondertara/joya/core/query/pagination/FieldParam.java b/src/main/java/com/sondertara/joya/core/query/pagination/FieldParam.java index 0149682..178790a 100644 --- a/src/main/java/com/sondertara/joya/core/query/pagination/FieldParam.java +++ b/src/main/java/com/sondertara/joya/core/query/pagination/FieldParam.java @@ -11,62 +11,34 @@ @Data public class FieldParam implements java.io.Serializable { - /** - * 字段名称 - */ - private String fieldName; - /** - * 字段值 - */ - private Object fieldValue; - /** - * 查询操作 - */ - private Operator operator; + /** 字段名称 */ + private String fieldName; + /** 字段值 */ + private Object fieldValue; + /** 查询操作 */ + private Operator operator; - /** - * 字段判断类型 - */ - public enum Operator { - /** - * 相等 - */ - EQ, - /** - * like - */ - LIKE, - /** - * 左like %kk - */ - LIKE_L, - /** - * 右like kk% - */ - LIKE_R, - /** - * 大于 - */ - GT, - /** - * 小于 - */ - LT, - /** - * 大于等于 - */ - GTE, - /** - * 小于等于 - */ - LTE, - /** - * IN范围查询 - */ - IN, - /** - * 不等 - */ - NEQ - } + /** 字段判断类型 */ + public enum Operator { + /** 相等 */ + EQ, + /** like */ + LIKE, + /** 左like %kk */ + LIKE_L, + /** 右like kk% */ + LIKE_R, + /** 大于 */ + GT, + /** 小于 */ + LT, + /** 大于等于 */ + GTE, + /** 小于等于 */ + LTE, + /** IN范围查询 */ + IN, + /** 不等 */ + NEQ + } } diff --git a/src/main/java/com/sondertara/joya/core/query/pagination/JoyaPageConvert.java b/src/main/java/com/sondertara/joya/core/query/pagination/JoyaPageConvert.java index 65804ca..9215c07 100644 --- a/src/main/java/com/sondertara/joya/core/query/pagination/JoyaPageConvert.java +++ b/src/main/java/com/sondertara/joya/core/query/pagination/JoyaPageConvert.java @@ -15,7 +15,6 @@ import java.util.List; import java.util.function.UnaryOperator; - /** * 构建分页对象 PageRequest 工具类 * @@ -23,107 +22,109 @@ */ public class JoyaPageConvert { - /** - * 带join查询 - * - * @param queryParam page query - * @param joinPart join part - * @return native sql - */ - public static NativeSqlQuery buildNativeQuery(PageQueryParam queryParam, UnaryOperator joinPart) { - - - return buildNativeQuery(queryParam, joinPart, new Class[0]); - } - - /** - * 联表查询 关联条件在 sqlStr中 - * - * @param queryParam page query - * @param targetClass the query table entity class - * @return native sql - */ - public static NativeSqlQuery buildNativeQuery(PageQueryParam queryParam, Class... targetClass) { + /** + * 带join查询 + * + * @param queryParam page query + * @param joinPart join part + * @return native sql + */ + public static NativeSqlQuery buildNativeQuery( + PageQueryParam queryParam, UnaryOperator joinPart) { + return buildNativeQuery(queryParam, joinPart, new Class[0]); + } - return buildNativeQuery(queryParam, null, targetClass); - } + /** + * 联表查询 关联条件在 sqlStr中 + * + * @param queryParam page query + * @param targetClass the query table entity class + * @return native sql + */ + public static NativeSqlQuery buildNativeQuery( + PageQueryParam queryParam, Class... targetClass) { + return buildNativeQuery(queryParam, null, targetClass); + } - @SuppressWarnings("unchecked") - private static NativeSqlQuery buildNativeQuery(PageQueryParam queryParam, UnaryOperator joinFunc, Class... targetClass) { - List searchParams = queryParam.getParams(); - UnaryOperator func = w -> { - if (CollectionUtils.isNotEmpty(queryParam.getCondition())) { - for (String s : queryParam.getCondition()) { - w.addCondition(s); - } + @SuppressWarnings("unchecked") + private static NativeSqlQuery buildNativeQuery( + PageQueryParam queryParam, UnaryOperator joinFunc, Class... targetClass) { + List searchParams = queryParam.getParams(); + UnaryOperator func = + w -> { + if (CollectionUtils.isNotEmpty(queryParam.getCondition())) { + for (String s : queryParam.getCondition()) { + w.addCondition(s); } - for (SearchParam searchParam : searchParams) { - String fieldName = searchParam.getFieldName(); - fieldName = SqlUtils.warpColumn(fieldName); - Object fieldValue = searchParam.getFieldValue(); - FieldParam.Operator operator = searchParam.getOperator(); - switch (operator) { - case EQ: - w.eq(fieldName, fieldValue); - break; - case NEQ: - w.ne(fieldName, fieldValue); - break; - case GT: - w.gt(fieldName, fieldValue); - break; - case GTE: - w.gte(fieldName, fieldValue); - break; - case LT: - w.lt(fieldName, fieldValue); - break; - case LTE: - w.lte(fieldName, fieldValue); - break; - case IN: - if (ArrayUtils.isArray(fieldValue)) { - w.in(fieldName, Arrays.asList((Object[]) fieldValue)); - } else if (fieldValue instanceof Collection) { - w.in(fieldName, (Collection) fieldValue); - } else { - throw new TaraException("The value of operator [IN] must be collection"); - } - break; - case LIKE: - w.contains(fieldName, fieldValue); - break; - case LIKE_L: - w.endsWith(fieldName, fieldValue); - break; - case LIKE_R: - w.startsWith(fieldName, fieldValue); - break; - - default: + } + for (SearchParam searchParam : searchParams) { + String fieldName = searchParam.getFieldName(); + fieldName = SqlUtils.warpColumn(fieldName); + Object fieldValue = searchParam.getFieldValue(); + FieldParam.Operator operator = searchParam.getOperator(); + switch (operator) { + case EQ: + w.eq(fieldName, fieldValue); + break; + case NEQ: + w.ne(fieldName, fieldValue); + break; + case GT: + w.gt(fieldName, fieldValue); + break; + case GTE: + w.gte(fieldName, fieldValue); + break; + case LT: + w.lt(fieldName, fieldValue); + break; + case LTE: + w.lte(fieldName, fieldValue); + break; + case IN: + if (ArrayUtils.isArray(fieldValue)) { + w.in(fieldName, Arrays.asList((Object[]) fieldValue)); + } else if (fieldValue instanceof Collection) { + w.in(fieldName, (Collection) fieldValue); + } else { + throw new TaraException("The value of operator [IN] must be collection"); } + break; + case LIKE: + w.contains(fieldName, fieldValue); + break; + case LIKE_L: + w.endsWith(fieldName, fieldValue); + break; + case LIKE_R: + w.startsWith(fieldName, fieldValue); + break; + + default: } - return w; + } + return w; }; - NativeSqlQueryBuilder builder = new NativeSqlQueryBuilder(); - if (null != queryParam.getColumns()) { - builder.wrapColumn(queryParam.getColumns().toArray(new String[0])); - } - builder.select(); - if (null != targetClass && targetClass.length > 0) { - builder.from(targetClass); - } else { - builder.from(joinFunc); - } + NativeSqlQueryBuilder builder = new NativeSqlQueryBuilder(); + if (null != queryParam.getColumns()) { + builder.wrapColumn(queryParam.getColumns().toArray(new String[0])); + } + builder.select(); + if (null != targetClass && targetClass.length > 0) { + builder.from(targetClass); + } else { + builder.from(joinFunc); + } - builder.where(func, PageQueryParam.LinkType.OR.equals(queryParam.getLinkType())); - List list = queryParam.getOrderList(); - for (OrderParam param : list) { - String orderBy = StringFormatter.format("{} {}", param.getFieldName(), param.getOrderType().toString()); - builder.orderBy(orderBy); - } - return builder.build(); + builder.where(func, PageQueryParam.LinkType.OR.equals(queryParam.getLinkType())); + List list = queryParam.getOrderList(); + for (OrderParam param : list) { + String orderBy = + StringFormatter.format("{} {}", param.getFieldName(), param.getOrderType().toString()); + builder.orderBy(orderBy); } + return builder.build(); + } } diff --git a/src/main/java/com/sondertara/joya/core/query/pagination/JoyaQuery.java b/src/main/java/com/sondertara/joya/core/query/pagination/JoyaQuery.java index 19fc480..443d8d4 100644 --- a/src/main/java/com/sondertara/joya/core/query/pagination/JoyaQuery.java +++ b/src/main/java/com/sondertara/joya/core/query/pagination/JoyaQuery.java @@ -14,30 +14,23 @@ @Data public abstract class JoyaQuery { - /** - * 特殊where语句 - */ - protected List condition = new ArrayList<>(); - - /** - * 指定from - */ - protected String from; - /** - * 特殊select 用来指定重名字段的别名 - */ - protected List columns; - - protected List getCondition() { - return condition; - } - - public void addCondition(String condition) { - this.condition.add(condition); - } - - - public void column(String... columns) { - this.columns = Lists.newArrayList(columns); - } + /** 特殊where语句 */ + protected List condition = new ArrayList<>(); + + /** 指定from */ + protected String from; + /** 特殊select 用来指定重名字段的别名 */ + protected List columns; + + protected List getCondition() { + return condition; + } + + public void addCondition(String condition) { + this.condition.add(condition); + } + + public void column(String... columns) { + this.columns = Lists.newArrayList(columns); + } } diff --git a/src/main/java/com/sondertara/joya/core/query/pagination/OrderParam.java b/src/main/java/com/sondertara/joya/core/query/pagination/OrderParam.java index 213a0fa..f4e441a 100644 --- a/src/main/java/com/sondertara/joya/core/query/pagination/OrderParam.java +++ b/src/main/java/com/sondertara/joya/core/query/pagination/OrderParam.java @@ -1,6 +1,5 @@ package com.sondertara.joya.core.query.pagination; - import lombok.Data; import java.io.Serializable; @@ -14,48 +13,35 @@ @Data public class OrderParam implements Serializable { - - /** - * - */ - private static final long serialVersionUID = -7226188298305059440L; - /** - * 排序字段 - */ - private String fieldName; - /** - * 排序方式 asc desc; - */ - private OrderBy orderType; - - public OrderParam(String fieldName, OrderBy orderType) { - - this.fieldName = fieldName; - this.orderType = orderType; - } - - public OrderParam(String fieldName) { - - this.fieldName = fieldName; - this.orderType = OrderBy.ASC; - } - - /** - * order parameter - * - * @author SonderTara - * @date 2021/11/14 17:55 - */ - public enum OrderBy { - /** - * asc - */ - ASC, - /** - * desc - */ - DESC - } - - + /** */ + private static final long serialVersionUID = -7226188298305059440L; + /** 排序字段 */ + private String fieldName; + /** 排序方式 asc desc; */ + private OrderBy orderType; + + public OrderParam(String fieldName, OrderBy orderType) { + + this.fieldName = fieldName; + this.orderType = orderType; + } + + public OrderParam(String fieldName) { + + this.fieldName = fieldName; + this.orderType = OrderBy.ASC; + } + + /** + * order parameter + * + * @author SonderTara + * @date 2021/11/14 17:55 + */ + public enum OrderBy { + /** asc */ + ASC, + /** desc */ + DESC + } } diff --git a/src/main/java/com/sondertara/joya/core/query/pagination/PageQueryParam.java b/src/main/java/com/sondertara/joya/core/query/pagination/PageQueryParam.java index bc67dfc..8bf12bf 100644 --- a/src/main/java/com/sondertara/joya/core/query/pagination/PageQueryParam.java +++ b/src/main/java/com/sondertara/joya/core/query/pagination/PageQueryParam.java @@ -6,7 +6,6 @@ import java.io.Serializable; import java.util.List; - /** * pagination param * @@ -15,90 +14,73 @@ */ @EqualsAndHashCode(callSuper = true) public class PageQueryParam extends JoyaQuery implements Serializable { - /** - * page size - * 分页大小 - */ - private Integer pageSize = 10; - /** - * page start default is zero - * 页数 默认从0开始 - */ - private Integer page = 0; - /** - * the query type,default is AND - * 连接类型 默认and - */ - private LinkType linkType = LinkType.AND; - /** - * the order param - * 排序字段 - */ - private List orderList = Lists.newArrayList(); - - /** - * the param of where - * 搜索参数 - */ - private List params = Lists.newArrayList(); - - public enum LinkType { - /** - * - */ - AND, OR - - } - - /** - * add search param - * - * @param filed fileName - * @param value value - * @param operator operator - */ - public void addSearchParam(String filed, Object value, FieldParam.Operator operator) { - - this.params.add(new SearchParam(filed, value, operator)); - } - - public Integer getPageSize() { - return pageSize; - } - - public void pageSize(Integer pageSize) { - this.pageSize = pageSize; - } - - public Integer getPage() { - return page; - } - - public void page(Integer page) { - this.page = page; - } - - public void linkType(LinkType linkType) { - this.linkType = linkType; - } - - public void setParams(List params) { - this.params = params; - } - - public List getParams() { - return params; - } - - public LinkType getLinkType() { - return linkType; - } - - public List getOrderList() { - return orderList; - } - - public void setOrderList(List orderList) { - this.orderList = orderList; - } + /** page size 分页大小 */ + private Integer pageSize = 10; + /** page start default is zero 页数 默认从0开始 */ + private Integer page = 0; + /** the query type,default is AND 连接类型 默认and */ + private LinkType linkType = LinkType.AND; + /** the order param 排序字段 */ + private List orderList = Lists.newArrayList(); + + /** the param of where 搜索参数 */ + private List params = Lists.newArrayList(); + + public enum LinkType { + /** */ + AND, + OR + } + + /** + * add search param + * + * @param filed fileName + * @param value value + * @param operator operator + */ + public void addSearchParam(String filed, Object value, FieldParam.Operator operator) { + + this.params.add(new SearchParam(filed, value, operator)); + } + + public Integer getPageSize() { + return pageSize; + } + + public void pageSize(Integer pageSize) { + this.pageSize = pageSize; + } + + public Integer getPage() { + return page; + } + + public void page(Integer page) { + this.page = page; + } + + public void linkType(LinkType linkType) { + this.linkType = linkType; + } + + public void setParams(List params) { + this.params = params; + } + + public List getParams() { + return params; + } + + public LinkType getLinkType() { + return linkType; + } + + public List getOrderList() { + return orderList; + } + + public void setOrderList(List orderList) { + this.orderList = orderList; + } } diff --git a/src/main/java/com/sondertara/joya/core/query/pagination/PageResult.java b/src/main/java/com/sondertara/joya/core/query/pagination/PageResult.java index e285934..c79156d 100644 --- a/src/main/java/com/sondertara/joya/core/query/pagination/PageResult.java +++ b/src/main/java/com/sondertara/joya/core/query/pagination/PageResult.java @@ -15,19 +15,19 @@ @Data public class PageResult implements Serializable { - private final Integer page; - private final Integer pageSize; - private final Long total; - private final List data; + private final Integer page; + private final Integer pageSize; + private final Long total; + private final List data; - public PageResult(Integer page, Integer pageSize, Long total, List data) { - this.page = page; - this.pageSize = pageSize; - this.total = total; - if (null == data) { - this.data = new ArrayList(); - } else { - this.data = data; - } + public PageResult(Integer page, Integer pageSize, Long total, List data) { + this.page = page; + this.pageSize = pageSize; + this.total = total; + if (null == data) { + this.data = new ArrayList(); + } else { + this.data = data; } + } } diff --git a/src/main/java/com/sondertara/joya/core/query/pagination/SearchParam.java b/src/main/java/com/sondertara/joya/core/query/pagination/SearchParam.java index 07c07d5..8e95f6b 100644 --- a/src/main/java/com/sondertara/joya/core/query/pagination/SearchParam.java +++ b/src/main/java/com/sondertara/joya/core/query/pagination/SearchParam.java @@ -9,39 +9,38 @@ */ @ToString public class SearchParam implements Serializable { - private static final long serialVersionUID = -2687523337885804193L; - private String fieldName; - private Object fieldValue; - private FieldParam.Operator operator; - - public SearchParam(String fieldName, Object fieldValue, FieldParam.Operator operator) { - this.fieldName = fieldName; - this.fieldValue = fieldValue; - this.operator = operator; - } - - public String getFieldName() { - return this.fieldName; - } - - public void setFieldName(String fieldName) { - this.fieldName = fieldName; - } - - - public FieldParam.Operator getOperator() { - return this.operator; - } - - public void setOperator(FieldParam.Operator operator) { - this.operator = operator; - } - - public Object getFieldValue() { - return fieldValue; - } - - public void setFieldValue(Object fieldValue) { - this.fieldValue = fieldValue; - } + private static final long serialVersionUID = -2687523337885804193L; + private String fieldName; + private Object fieldValue; + private FieldParam.Operator operator; + + public SearchParam(String fieldName, Object fieldValue, FieldParam.Operator operator) { + this.fieldName = fieldName; + this.fieldValue = fieldValue; + this.operator = operator; + } + + public String getFieldName() { + return this.fieldName; + } + + public void setFieldName(String fieldName) { + this.fieldName = fieldName; + } + + public FieldParam.Operator getOperator() { + return this.operator; + } + + public void setOperator(FieldParam.Operator operator) { + this.operator = operator; + } + + public Object getFieldValue() { + return fieldValue; + } + + public void setFieldValue(Object fieldValue) { + this.fieldValue = fieldValue; + } } diff --git a/src/main/java/com/sondertara/joya/domain/AuditableEntity.java b/src/main/java/com/sondertara/joya/domain/AuditableEntity.java index fb0ea13..73dd266 100644 --- a/src/main/java/com/sondertara/joya/domain/AuditableEntity.java +++ b/src/main/java/com/sondertara/joya/domain/AuditableEntity.java @@ -14,80 +14,83 @@ import java.io.Serializable; import java.util.Date; - /** - * 类将不是一个完整的实体类,他将不会映射到数据库表,但是他的属性都将映射到其子类的数据库字段中。 //http://blog.sina.com.cn/s/blog_7085382f0100uk4p.html - *

- * //@JsonIgnoreProperties(value = {"createdDate","createdBy", "lastModifiedDate", "lastModifiedBy"},allowGetters = true) //jackson只能获取createdDate,createdBy,lastModifiedDate,lastModifiedBy属性(其他创建和更新操作都由jpa完成) - * 用于监听实体类操作的 + * 类将不是一个完整的实体类,他将不会映射到数据库表,但是他的属性都将映射到其子类的数据库字段中。 + * //http://blog.sina.com.cn/s/blog_7085382f0100uk4p.html + * + *

//@JsonIgnoreProperties(value = {"createdDate","createdBy", "lastModifiedDate", + * "lastModifiedBy"},allowGetters = true) + * //jackson只能获取createdDate,createdBy,lastModifiedDate,lastModifiedBy属性(其他创建和更新操作都由jpa完成) 用于监听实体类操作的 * * @author huangxiaohu */ @EntityListeners({AuditingEntityListener.class}) @MappedSuperclass -public abstract class AuditableEntity, ID extends Serializable> extends BaseEntity { - - /** - * 表示该字段为创建时间字段,在这个实体被insert的时候,会设置值. 类上加@EntityListeners(AuditingEntityListener.class),启动类加@EnableJpaAuditing. @LastModifiedDate同理. - */ - @Column(name = "create_time", nullable = false, updatable = false) - @Temporal(TemporalType.TIMESTAMP) - @CreatedDate - protected Date createTime; - - /** - * 表示该字段为创建人,在这个实体被insert的时候,会设置值.类上加@EntityListeners(AuditingEntityListener.class),启动类加@EnableJpaAuditing. 有实现AuditorAware接口的配置类. @LastModifiedBy同理 - */ - @Column(name = "create_by", nullable = false, updatable = false) - @CreatedBy - protected Long createBy; - - @Column(name = "update_time", nullable = false) - @Temporal(TemporalType.TIMESTAMP) - @LastModifiedDate - protected Date updateTime; - - @Column(name = "update_by", nullable = false) - @LastModifiedBy - protected Long updateBy; - - public AuditableEntity() { - } - - public AuditableEntity(Date createDate, Long createdBy, Date lastModifiedDate, Long lastModifiedBy) { - super(); - } - - - public Date getCreateTime() { - return createTime; - } - - public void setCreateTime(Date createTime) { - this.createTime = createTime; - } - - public Long getCreateBy() { - return createBy; - } - - public void setCreateBy(Long createBy) { - this.createBy = createBy; - } - - public Date getUpdateTime() { - return updateTime; - } - - public void setUpdateTime(Date updateTime) { - this.updateTime = updateTime; - } - - public Long getUpdateBy() { - return updateBy; - } - - public void setUpdateBy(Long updateBy) { - this.updateBy = updateBy; - } +public abstract class AuditableEntity, ID extends Serializable> + extends BaseEntity { + + /** + * 表示该字段为创建时间字段,在这个实体被insert的时候,会设置值. + * 类上加@EntityListeners(AuditingEntityListener.class),启动类加@EnableJpaAuditing. @LastModifiedDate同理. + */ + @Column(name = "create_time", nullable = false, updatable = false) + @Temporal(TemporalType.TIMESTAMP) + @CreatedDate + protected Date createTime; + + /** + * 表示该字段为创建人,在这个实体被insert的时候,会设置值.类上加@EntityListeners(AuditingEntityListener.class),启动类加@EnableJpaAuditing. + * 有实现AuditorAware接口的配置类. @LastModifiedBy同理 + */ + @Column(name = "create_by", nullable = false, updatable = false) + @CreatedBy + protected Long createBy; + + @Column(name = "update_time", nullable = false) + @Temporal(TemporalType.TIMESTAMP) + @LastModifiedDate + protected Date updateTime; + + @Column(name = "update_by", nullable = false) + @LastModifiedBy + protected Long updateBy; + + public AuditableEntity() {} + + public AuditableEntity( + Date createDate, Long createdBy, Date lastModifiedDate, Long lastModifiedBy) { + super(); + } + + public Date getCreateTime() { + return createTime; + } + + public void setCreateTime(Date createTime) { + this.createTime = createTime; + } + + public Long getCreateBy() { + return createBy; + } + + public void setCreateBy(Long createBy) { + this.createBy = createBy; + } + + public Date getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(Date updateTime) { + this.updateTime = updateTime; + } + + public Long getUpdateBy() { + return updateBy; + } + + public void setUpdateBy(Long updateBy) { + this.updateBy = updateBy; + } } diff --git a/src/main/java/com/sondertara/joya/domain/BaseEntity.java b/src/main/java/com/sondertara/joya/domain/BaseEntity.java index eb55be3..8d24305 100644 --- a/src/main/java/com/sondertara/joya/domain/BaseEntity.java +++ b/src/main/java/com/sondertara/joya/domain/BaseEntity.java @@ -1,6 +1,5 @@ package com.sondertara.joya.domain; - import com.alibaba.fastjson.annotation.JSONField; import com.sondertara.common.util.LocalDateTimeUtils; import com.sondertara.common.util.StringUtils; @@ -13,75 +12,72 @@ import java.util.HashMap; import java.util.Map; - /** - * 类将不是一个完整的实体类,他将不会映射到数据库表,但是他的属性都将映射到其子类的数据库字段中。 - * 用于监听实体类操作的 + * 类将不是一个完整的实体类,他将不会映射到数据库表,但是他的属性都将映射到其子类的数据库字段中。 用于监听实体类操作的 * * @author SonderTara */ @MappedSuperclass @EntityListeners({BaseEntityListener.class}) -public abstract class BaseEntity, ID extends Serializable> extends Model { - - /** - * 请求参数(只是查询需要用到,实体类属性不需要有) - * 例如: params["ids"]=[10000,10010,10086] - * 例如: params["createTime"]=["2049-01-01","2049-12-12"] - */ - @Transient - @JSONField(serialize = false) - private Map params; - - - public BaseEntity setParams(Map params) { - this.params = params; - return this; +public abstract class BaseEntity, ID extends Serializable> + extends Model { + + /** + * 请求参数(只是查询需要用到,实体类属性不需要有) 例如: params["ids"]=[10000,10010,10086] 例如: + * params["createTime"]=["2049-01-01","2049-12-12"] + */ + @Transient + @JSONField(serialize = false) + private Map params; + + public BaseEntity setParams(Map params) { + this.params = params; + return this; + } + + public void putParam(String key, Object value) { + if (this.params == null) { + params = new HashMap<>(16); } + this.params.put(key, value); + } - public void putParam(String key, Object value) { - if (this.params == null) { - params = new HashMap<>(16); - } - this.params.put(key, value); + public Object getParams(String fieldName) { + if (params == null) { + return null; } - - public Object getParams(String fieldName) { - if (params == null) { - return null; - } - Object values = params.get(fieldName); - if (values == null) { - return null; - } - if (values.getClass().isArray()) { - Object[] objects = ((Object[]) values); - - - if ((StringUtils.endWith(fieldName, "Time", true) || StringUtils.endWith(fieldName, "Date", true))) { - if (objects.length == 2) { - return Arrays.asList(LocalDateTimeUtils.parseToDate((String) objects[0]), LocalDateTimeUtils.parseToDate((String) objects[1])); - } - } - return Arrays.asList(objects); - } - - return values; + Object values = params.get(fieldName); + if (values == null) { + return null; } - - @Override - @JSONField(serialize = false) - public boolean isNew() { - return null == getId(); + if (values.getClass().isArray()) { + Object[] objects = ((Object[]) values); + + if ((StringUtils.endWith(fieldName, "Time", true) + || StringUtils.endWith(fieldName, "Date", true))) { + if (objects.length == 2) { + return Arrays.asList( + LocalDateTimeUtils.parseToDate((String) objects[0]), + LocalDateTimeUtils.parseToDate((String) objects[1])); + } + } + return Arrays.asList(objects); } - /** - * 返回ID - * - * @return id - */ - @Override - public abstract ID getId(); - - + return values; + } + + @Override + @JSONField(serialize = false) + public boolean isNew() { + return null == getId(); + } + + /** + * 返回ID + * + * @return id + */ + @Override + public abstract ID getId(); } diff --git a/src/main/java/com/sondertara/joya/domain/BaseEntityListener.java b/src/main/java/com/sondertara/joya/domain/BaseEntityListener.java index 05c0ebf..15e65d3 100644 --- a/src/main/java/com/sondertara/joya/domain/BaseEntityListener.java +++ b/src/main/java/com/sondertara/joya/domain/BaseEntityListener.java @@ -1,6 +1,5 @@ package com.sondertara.joya.domain; - import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Configurable; @@ -19,33 +18,33 @@ */ @Slf4j @Configurable -//@CreatedDate @LastModifiedDate 由AuditingEntityListener完成 -//@CreatedBy LastModifiedBy 由CurrentUserAuditor完成 +// @CreatedDate @LastModifiedDate 由AuditingEntityListener完成 +// @CreatedBy LastModifiedBy 由CurrentUserAuditor完成 public class BaseEntityListener { - /*@PrePersist - public void touchForCreate(BaseEntity domain){ - domain.setDelFlag(BaseEntity.DEL_FLAG_NORMAL); - //log.info("开始保存------>"+domain.toString()); - } - - - @PreUpdate - public void touchForUpdate(BaseEntity domain){ - if (null == domain.getDelFlag()){ - domain.setDelFlag(BaseEntity.DEL_FLAG_NORMAL); - } - //log.info("开始更新------>"+domain.toString()); - } - - @PostPersist - public void PostPersist(Object domain){ - log.info("保存完毕------>"+domain.toString()); - } - - @PostUpdate - public void PostUpdate(Object domain){ - log.info("更新完毕------>"+domain.toString()); - }*/ + /*@PrePersist + public void touchForCreate(BaseEntity domain){ + domain.setDelFlag(BaseEntity.DEL_FLAG_NORMAL); + //log.info("开始保存------>"+domain.toString()); + } + + + @PreUpdate + public void touchForUpdate(BaseEntity domain){ + if (null == domain.getDelFlag()){ + domain.setDelFlag(BaseEntity.DEL_FLAG_NORMAL); + } + //log.info("开始更新------>"+domain.toString()); + } + + @PostPersist + public void PostPersist(Object domain){ + log.info("保存完毕------>"+domain.toString()); + } + + @PostUpdate + public void PostUpdate(Object domain){ + log.info("更新完毕------>"+domain.toString()); + }*/ } diff --git a/src/main/java/com/sondertara/joya/domain/Model.java b/src/main/java/com/sondertara/joya/domain/Model.java index 77fe060..8dafc92 100644 --- a/src/main/java/com/sondertara/joya/domain/Model.java +++ b/src/main/java/com/sondertara/joya/domain/Model.java @@ -1,6 +1,5 @@ package com.sondertara.joya.domain; - import com.sondertara.common.util.StringUtils; import com.sondertara.joya.jpa.repository.BaseRepository; import org.springframework.context.ApplicationContext; @@ -14,70 +13,64 @@ import java.util.Objects; /** - * 具备增删查功能的实体父类 - * T为实体自身类型,ID为实体主键类型 + * 具备增删查功能的实体父类 T为实体自身类型,ID为实体主键类型 * * @author huangxiaohu */ public abstract class Model implements Serializable, Persistable { - private static final long serialVersionUID = 6882139672754605640L; - - /** - * 用于获取容器中bean对象的上下文,由外部用Model.setApplicationContext方法传入 - */ - private static ApplicationContext applicationContext; - /** - * 维护各个实体类对应的CrudRepository对象,避免重复调用applicationContext.getBean方法影响性能 - */ - private Map> repositories = new HashMap<>(); + private static final long serialVersionUID = 6882139672754605640L; - public static void setApplicationContext(ApplicationContext applicationContext) { - Model.applicationContext = applicationContext; - } + /** 用于获取容器中bean对象的上下文,由外部用Model.setApplicationContext方法传入 */ + private static ApplicationContext applicationContext; + /** 维护各个实体类对应的CrudRepository对象,避免重复调用applicationContext.getBean方法影响性能 */ + private Map> repositories = new HashMap<>(); - @PersistenceContext - @SuppressWarnings("unchecked") - private BaseRepository getRepository() { - // 1.获取实体对象对应的CrudRepository的bean名称,这里根据具体的命名风格来调整 - String entityClassName = getClass().getSimpleName(); - String beanName = StringUtils.lowerFirst(entityClassName) + "Repository"; - BaseRepository baseRepository = repositories.get(beanName); - // 2.如果map中没有,从上下文环境获取,并放进map中 - if (Objects.isNull(baseRepository)) { - baseRepository = (BaseRepository) applicationContext.getBean(beanName); - repositories.put(beanName, baseRepository); - } - // 3. 返回 - return baseRepository; - } + public static void setApplicationContext(ApplicationContext applicationContext) { + Model.applicationContext = applicationContext; + } - /** - * 保存当前对象 - * - * @return 保存后的当前对象 - */ - @SuppressWarnings("unchecked") - @Transactional(rollbackFor = Exception.class) - public T save() { - return getRepository().save((T) this); + @PersistenceContext + @SuppressWarnings("unchecked") + private BaseRepository getRepository() { + // 1.获取实体对象对应的CrudRepository的bean名称,这里根据具体的命名风格来调整 + String entityClassName = getClass().getSimpleName(); + String beanName = StringUtils.lowerFirst(entityClassName) + "Repository"; + BaseRepository baseRepository = repositories.get(beanName); + // 2.如果map中没有,从上下文环境获取,并放进map中 + if (Objects.isNull(baseRepository)) { + baseRepository = (BaseRepository) applicationContext.getBean(beanName); + repositories.put(beanName, baseRepository); } + // 3. 返回 + return baseRepository; + } - /** - * 根据当前对象的id获取对象 - * - * @return 查询到的对象 - */ + /** + * 保存当前对象 + * + * @return 保存后的当前对象 + */ + @SuppressWarnings("unchecked") + @Transactional(rollbackFor = Exception.class) + public T save() { + return getRepository().save((T) this); + } - public T findById() { - return getRepository().findById(Objects.requireNonNull(getId())).orElseThrow(() -> new NullPointerException("ID is null")); - } + /** + * 根据当前对象的id获取对象 + * + * @return 查询到的对象 + */ + public T findById() { + return getRepository() + .findById(Objects.requireNonNull(getId())) + .orElseThrow(() -> new NullPointerException("ID is null")); + } - /** - * 删除当前对象 - */ - @SuppressWarnings("unchecked") - @Transactional(rollbackFor = Exception.class) - public void delete() { - getRepository().delete((T) this); - } + /** 删除当前对象 */ + @SuppressWarnings("unchecked") + @Transactional(rollbackFor = Exception.class) + public void delete() { + getRepository().delete((T) this); + } } diff --git a/src/main/java/com/sondertara/joya/domain/PersistEntity.java b/src/main/java/com/sondertara/joya/domain/PersistEntity.java index 2358a14..d37d14d 100644 --- a/src/main/java/com/sondertara/joya/domain/PersistEntity.java +++ b/src/main/java/com/sondertara/joya/domain/PersistEntity.java @@ -9,14 +9,13 @@ * @author huangxiaohu */ public class PersistEntity implements Serializable { - @Transient - private boolean isNew = true; + @Transient private boolean isNew = true; - public boolean isNew() { - return isNew; - } + public boolean isNew() { + return isNew; + } - public void setNew(boolean aNew) { - isNew = aNew; - } + public void setNew(boolean aNew) { + isNew = aNew; + } } diff --git a/src/main/java/com/sondertara/joya/enums/DbType.java b/src/main/java/com/sondertara/joya/enums/DbType.java index 63f5b59..cf2e24e 100644 --- a/src/main/java/com/sondertara/joya/enums/DbType.java +++ b/src/main/java/com/sondertara/joya/enums/DbType.java @@ -3,7 +3,6 @@ import com.sondertara.common.exception.TaraException; import lombok.Getter; - /** * @author huangxiaohu * @date 2021/8/27 22:14 @@ -11,26 +10,25 @@ @Getter public enum DbType { - /** - * 数据库类型 - */ - MYSQL("MYSQL", "com.mysql.cj.jdbc.Driver"), ORACLE("ORACLE", "oracle.jdbc.driver.OracleDriver"); + /** 数据库类型 */ + MYSQL("MYSQL", "com.mysql.cj.jdbc.Driver"), + ORACLE("ORACLE", "oracle.jdbc.driver.OracleDriver"); - private final String type; - private final String driverClassName; + private final String type; + private final String driverClassName; - DbType(String type, String driverClassName) { + DbType(String type, String driverClassName) { - this.type = type; - this.driverClassName = driverClassName; - } + this.type = type; + this.driverClassName = driverClassName; + } - public static DbType getDbType(String type) { - for (DbType dbTypeEnum : DbType.values()) { - if (dbTypeEnum.getType().equals(type)) { - return dbTypeEnum; - } - } - throw new TaraException("不支持的数据库类型:{}", type); + public static DbType getDbType(String type) { + for (DbType dbTypeEnum : DbType.values()) { + if (dbTypeEnum.getType().equals(type)) { + return dbTypeEnum; + } } + throw new TaraException("不支持的数据库类型:{}", type); + } } diff --git a/src/main/java/com/sondertara/joya/enums/EnvEnum.java b/src/main/java/com/sondertara/joya/enums/EnvEnum.java index 2f82fa6..44bd6ec 100644 --- a/src/main/java/com/sondertara/joya/enums/EnvEnum.java +++ b/src/main/java/com/sondertara/joya/enums/EnvEnum.java @@ -5,38 +5,38 @@ * @date 2021/7/9 15:20 */ public enum EnvEnum { - /** - * 测试,开发,预发,线上 - */ - TEST(0, "test"), DEV(1, "dev"), PREPUB(2, "prepub"), PROD(3, "prod"); + /** 测试,开发,预发,线上 */ + TEST(0, "test"), + DEV(1, "dev"), + PREPUB(2, "prepub"), + PROD(3, "prod"); + private final int code; + private final String name; - private final int code; - private final String name; + EnvEnum(int code, String name) { + this.code = code; + this.name = name; + } - EnvEnum(int code, String name) { - this.code = code; - this.name = name; + public static EnvEnum getEnum(String name) { + if (null == name) { + return null; } - - public static EnvEnum getEnum(String name) { - if (null == name) { - return null; - } - final EnvEnum[] enums = EnvEnum.values(); - for (EnvEnum envEnum : enums) { - if (envEnum.getName().equalsIgnoreCase(name)) { - return envEnum; - } - } - return null; + final EnvEnum[] enums = EnvEnum.values(); + for (EnvEnum envEnum : enums) { + if (envEnum.getName().equalsIgnoreCase(name)) { + return envEnum; + } } + return null; + } - public int getCode() { - return code; - } + public int getCode() { + return code; + } - public String getName() { - return name; - } + public String getName() { + return name; + } } diff --git a/src/main/java/com/sondertara/joya/enums/ReqResultCode.java b/src/main/java/com/sondertara/joya/enums/ReqResultCode.java index 4e98070..469fe01 100644 --- a/src/main/java/com/sondertara/joya/enums/ReqResultCode.java +++ b/src/main/java/com/sondertara/joya/enums/ReqResultCode.java @@ -6,54 +6,34 @@ * @author huangxiaohu * @date 2021/7/21 9:56 */ - public enum ReqResultCode { - /** - * 参数为空 - */ - PARAM_EMPTY("PARAM_EMPTY"), - /** - * 参数错误 - */ - PARAM_ERROR("PARAM_ERROR"), - /** - * 没有数据 - */ - NO_DATA("NO_DATA"), - /** - * 请求连接超时 - */ - CONNECT_TIMEOUT("CONNECT_TIMEOUT"), - CONNECT_REFUSED("CONNECT_REFUSED"), - /** - * 获取响应数据超时 - */ - READ_TIMEOUT("READ_TIMEOUT"), - /** - * Socket 连接超时 - */ - SOCKET_TIMEOUT("SOCKET_TIMEOUT"), - /** - * 请求资源异常 - */ - RESOURCE_REQUEST_ERROR("RESOURCE_REQUEST_ERROR"), - /** - * 请求异常 - */ - REQUEST_ERROR("REQUEST_ERROR"), - /** - * 系统错误 - */ - SYSTEM_ERROR("SYSTEM_ERROR"), - ; - private String code; - - ReqResultCode(String code) { - this.code = code; - } + /** 参数为空 */ + PARAM_EMPTY("PARAM_EMPTY"), + /** 参数错误 */ + PARAM_ERROR("PARAM_ERROR"), + /** 没有数据 */ + NO_DATA("NO_DATA"), + /** 请求连接超时 */ + CONNECT_TIMEOUT("CONNECT_TIMEOUT"), + CONNECT_REFUSED("CONNECT_REFUSED"), + /** 获取响应数据超时 */ + READ_TIMEOUT("READ_TIMEOUT"), + /** Socket 连接超时 */ + SOCKET_TIMEOUT("SOCKET_TIMEOUT"), + /** 请求资源异常 */ + RESOURCE_REQUEST_ERROR("RESOURCE_REQUEST_ERROR"), + /** 请求异常 */ + REQUEST_ERROR("REQUEST_ERROR"), + /** 系统错误 */ + SYSTEM_ERROR("SYSTEM_ERROR"), + ; + private String code; - public String getCode() { - return code; - } + ReqResultCode(String code) { + this.code = code; + } + public String getCode() { + return code; + } } diff --git a/src/main/java/com/sondertara/joya/ext/JoyaSpringContext.java b/src/main/java/com/sondertara/joya/ext/JoyaSpringContext.java index a618c9b..1e689ef 100644 --- a/src/main/java/com/sondertara/joya/ext/JoyaSpringContext.java +++ b/src/main/java/com/sondertara/joya/ext/JoyaSpringContext.java @@ -21,187 +21,189 @@ * * @author huangxiaohu */ - public class JoyaSpringContext implements ApplicationContextAware { - private static ApplicationContext applicationContext; - - /** - * register a bean - * - * @param name bean name - * @param clazz bean class - * @param args the args of constructor - * @param generic - * @return managed bean - */ - @SuppressWarnings({"unchecked"}) - public static T registerBean(String name, Class clazz, Object... args) { - Assert.isTrue(getApplicationContext() instanceof ConfigurableApplicationContext, - "ApplicationContext does not implement ConfigurableApplicationContext"); - - //convert applicationContext to ConfigurableApplicationContext - ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) applicationContext; - if (configurableApplicationContext.containsBean(name)) { - Object bean = configurableApplicationContext.getBean(name); - if (bean.getClass().isAssignableFrom(clazz)) { - return (T) bean; - } else { - throw new RuntimeException("BeanName 重复 " + name); - } - } - BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(clazz); - - for (Object arg : args) { - beanDefinitionBuilder.addConstructorArgValue(arg); - } - - BeanDefinition beanDefinition = beanDefinitionBuilder.getRawBeanDefinition(); - BeanDefinitionRegistry definitionRegistry = (BeanDefinitionRegistry) configurableApplicationContext.getBeanFactory(); - definitionRegistry.registerBeanDefinition(name, beanDefinition); - return getApplicationContext().getBean(name, clazz); - } - - public static ApplicationContext getApplicationContext() { - return applicationContext; - } - - @Override - public void setApplicationContext(@NonNull ApplicationContext context) throws BeansException { - applicationContext = context; - } - - /** - * get bean by name - * - * @param name the bean name - * @return managed bean - */ - public static Object getBean(String name) { - return getApplicationContext().getBean(name); - } - - /** - * get bean by class - * - * @param clazz the bean class - * @param generic - * @return managed bean - */ - public static T getBean(Class clazz) { - return getApplicationContext().getBean(clazz); - } - - /** - * get bean by name and class - * - * @param name the bean name - * @param clazz the bean class - * @param generic - * @return managed bean - */ - public static T getBean(String name, Class clazz) { - return getApplicationContext().getBean(name, clazz); + private static ApplicationContext applicationContext; + + /** + * register a bean + * + * @param name bean name + * @param clazz bean class + * @param args the args of constructor + * @param generic + * @return managed bean + */ + @SuppressWarnings({"unchecked"}) + public static T registerBean(String name, Class clazz, Object... args) { + Assert.isTrue( + getApplicationContext() instanceof ConfigurableApplicationContext, + "ApplicationContext does not implement ConfigurableApplicationContext"); + + // convert applicationContext to ConfigurableApplicationContext + ConfigurableApplicationContext configurableApplicationContext = + (ConfigurableApplicationContext) applicationContext; + if (configurableApplicationContext.containsBean(name)) { + Object bean = configurableApplicationContext.getBean(name); + if (bean.getClass().isAssignableFrom(clazz)) { + return (T) bean; + } else { + throw new RuntimeException("BeanName 重复 " + name); + } } + BeanDefinitionBuilder beanDefinitionBuilder = + BeanDefinitionBuilder.genericBeanDefinition(clazz); - - /** - * get all bean of interface implements - * - * @param clazz the interface class - * @param generic - * @return bean map - */ - public static Map getBeans(Class clazz) { - return getApplicationContext().getBeansOfType(clazz); - } - - /** - * remove bean - * - * @param beanName name - */ - public static void removeBean(String beanName) { - DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) getApplicationContext().getAutowireCapableBeanFactory(); - defaultListableBeanFactory.removeBeanDefinition(beanName); + for (Object arg : args) { + beanDefinitionBuilder.addConstructorArgValue(arg); } - - /** - * publish event - * - * @param event the event - */ - public static void publishEvent(ApplicationEvent event) { - if (getApplicationContext() == null) { - return; - } - getApplicationContext().publishEvent(event); + BeanDefinition beanDefinition = beanDefinitionBuilder.getRawBeanDefinition(); + BeanDefinitionRegistry definitionRegistry = + (BeanDefinitionRegistry) configurableApplicationContext.getBeanFactory(); + definitionRegistry.registerBeanDefinition(name, beanDefinition); + return getApplicationContext().getBean(name, clazz); + } + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + @Override + public void setApplicationContext(@NonNull ApplicationContext context) throws BeansException { + applicationContext = context; + } + + /** + * get bean by name + * + * @param name the bean name + * @return managed bean + */ + public static Object getBean(String name) { + return getApplicationContext().getBean(name); + } + + /** + * get bean by class + * + * @param clazz the bean class + * @param generic + * @return managed bean + */ + public static T getBean(Class clazz) { + return getApplicationContext().getBean(clazz); + } + + /** + * get bean by name and class + * + * @param name the bean name + * @param clazz the bean class + * @param generic + * @return managed bean + */ + public static T getBean(String name, Class clazz) { + return getApplicationContext().getBean(name, clazz); + } + + /** + * get all bean of interface implements + * + * @param clazz the interface class + * @param generic + * @return bean map + */ + public static Map getBeans(Class clazz) { + return getApplicationContext().getBeansOfType(clazz); + } + + /** + * remove bean + * + * @param beanName name + */ + public static void removeBean(String beanName) { + DefaultListableBeanFactory defaultListableBeanFactory = + (DefaultListableBeanFactory) getApplicationContext().getAutowireCapableBeanFactory(); + defaultListableBeanFactory.removeBeanDefinition(beanName); + } + + /** + * publish event + * + * @param event the event + */ + public static void publishEvent(ApplicationEvent event) { + if (getApplicationContext() == null) { + return; } - - /** - * get config - * - * @param key key the config key eg: tara.sql.enabled - * @return the config string value - */ - public static String getConfig(String key) { - - return getApplicationContext().getEnvironment().getProperty(key); + getApplicationContext().publishEvent(event); + } + + /** + * get config + * + * @param key key the config key eg: tara.sql.enabled + * @return the config string value + */ + public static String getConfig(String key) { + + return getApplicationContext().getEnvironment().getProperty(key); + } + + /** + * get config with default value + * + *

if the config is not exist will return the default value + * + * @param key key + * @param defaultValue default value + * @return the config string value + */ + public static String getConfig(String key, String defaultValue) { + + return getApplicationContext().getEnvironment().getProperty(key, defaultValue); + } + + /** + * get Boolean config + * + * @param key key + * @param defaultValue default value + * @return the config string value + */ + public static Boolean getConfig(String key, Boolean defaultValue) { + + return Boolean.valueOf( + getApplicationContext().getEnvironment().getProperty(key, String.valueOf(defaultValue))); + } + + /** + * get current environment + * + * @return the environment + * @see EnvEnum + */ + public static EnvEnum getEnv() { + EnvEnum envEnum; + String env = System.getProperty("env"); + if (StringUtils.isBlank(env)) { + env = System.getProperty("ENV"); } - - /** - * get config with default value - *

- * if the config is not exist will return the default value - * - * @param key key - * @param defaultValue default value - * @return the config string value - */ - public static String getConfig(String key, String defaultValue) { - - return getApplicationContext().getEnvironment().getProperty(key, defaultValue); + if (StringUtils.isBlank(env)) { + env = System.getProperty("spring.profiles.active"); } - - /** - * get Boolean config - * - * @param key key - * @param defaultValue default value - * @return the config string value - */ - public static Boolean getConfig(String key, Boolean defaultValue) { - - return Boolean.valueOf(getApplicationContext().getEnvironment().getProperty(key, String.valueOf(defaultValue))); - } - - /** - * get current environment - * - * @return the environment - * @see EnvEnum - */ - public static EnvEnum getEnv() { - EnvEnum envEnum; - String env = System.getProperty("env"); - if (StringUtils.isBlank(env)) { - env = System.getProperty("ENV"); + envEnum = EnvEnum.getEnum(env); + if (null == envEnum) { + final String[] profiles = getApplicationContext().getEnvironment().getActiveProfiles(); + for (String profile : profiles) { + envEnum = EnvEnum.getEnum(profile); + if (null != envEnum) { + break; } - if (StringUtils.isBlank(env)) { - env = System.getProperty("spring.profiles.active"); - } - envEnum = EnvEnum.getEnum(env); - if (null == envEnum) { - final String[] profiles = getApplicationContext().getEnvironment().getActiveProfiles(); - for (String profile : profiles) { - envEnum = EnvEnum.getEnum(profile); - if (null != envEnum) { - break; - } - } - } - return envEnum; - + } } -} \ No newline at end of file + return envEnum; + } +} diff --git a/src/main/java/com/sondertara/joya/hibernate/transformer/AliasToBeanTransformer.java b/src/main/java/com/sondertara/joya/hibernate/transformer/AliasToBeanTransformer.java index 4447783..0a8bf1f 100644 --- a/src/main/java/com/sondertara/joya/hibernate/transformer/AliasToBeanTransformer.java +++ b/src/main/java/com/sondertara/joya/hibernate/transformer/AliasToBeanTransformer.java @@ -15,7 +15,6 @@ import java.util.Map; import java.util.Objects; - /** * bean transformer * @@ -23,115 +22,112 @@ */ public class AliasToBeanTransformer implements ResultTransformer { - /** - * - */ - private final Class mappedClass; - private final Map mappedFields; - private final ValueSetter valueSetter; - - public AliasToBeanTransformer(Class mappedClass) { - this.mappedClass = mappedClass; - MappedFieldsInitializer mappedFieldsInitializer = new MappedFieldsInitializer(); - this.mappedFields = mappedFieldsInitializer.init(mappedClass); - this.valueSetter = new ValueSetter(); + /** */ + private final Class mappedClass; + + private final Map mappedFields; + private final ValueSetter valueSetter; + + public AliasToBeanTransformer(Class mappedClass) { + this.mappedClass = mappedClass; + MappedFieldsInitializer mappedFieldsInitializer = new MappedFieldsInitializer(); + this.mappedFields = mappedFieldsInitializer.init(mappedClass); + this.valueSetter = new ValueSetter(); + } + + @Override + public Object transformTuple(Object[] tuple, String[] aliases) { + if (CollectionUtils.isEmpty(mappedFields)) { + if (isPrimitive(mappedClass) + || String.class.isAssignableFrom(mappedClass) + || Date.class.isAssignableFrom(mappedClass)) { + return setSingleField(tuple); + } } + T mappedObject = BeanUtils.instantiateClass(mappedClass); + for (int i = 0; i < aliases.length; i++) { + String alias = StringUtils.toCamelCase(aliases[i].trim()); + Object value = tuple[i]; + valueSetter.set(mappedObject, alias, value, this.mappedFields); + } + valueSetter.clearGenericMap(); + return mappedObject; + } + + @SuppressWarnings("rawtypes") + @Override + public List transformList(List list) { + return list; + } + + public final Class getMappedClass() { + return this.mappedClass; + } + + /** + * set single value + * + * @param tuple value + * @return value after transformed + */ + private Object setSingleField(Object[] tuple) { + if (tuple.length < 1) { + return null; + } + Object value = tuple[0]; + if (isPrimitive(mappedClass)) { + if (Character.class.isAssignableFrom(mappedClass)) { + throw new IllegalArgumentException("Not support Character!"); + } + for (Constructor constructor : mappedClass.getDeclaredConstructors()) { + try { + int count = constructor.getParameterCount(); + if (count == 1) { + if (String.class.isAssignableFrom(constructor.getParameterTypes()[0])) { - @Override - public Object transformTuple(Object[] tuple, String[] aliases) { - if (CollectionUtils.isEmpty(mappedFields)) { - if (isPrimitive(mappedClass) || String.class.isAssignableFrom(mappedClass) || Date.class.isAssignableFrom(mappedClass)) { - return setSingleField(tuple); - + if (Objects.isNull(value)) { + return null; + } else { + return constructor.newInstance(value.toString()); + } } + } + } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) { + throw new RuntimeException(e); } - T mappedObject = BeanUtils.instantiateClass(mappedClass); - - for (int i = 0; i < aliases.length; i++) { - String alias = StringUtils.toCamelCase(aliases[i].trim()); - Object value = tuple[i]; - valueSetter.set(mappedObject, alias, value, this.mappedFields); - } - valueSetter.clearGenericMap(); - return mappedObject; + } } - - @SuppressWarnings("rawtypes") - @Override - public List transformList(List list) { - return list; + if (String.class.equals(mappedClass)) { + if (Objects.isNull(value)) { + return null; + } else { + return value.toString(); + } } - public final Class getMappedClass() { - return this.mappedClass; + if (Date.class.equals(mappedClass)) { + if (value instanceof TIMESTAMP) { + return SqlDataHelper.extractDate(value); + } + return value; } - /** - * set single value - * - * @param tuple value - * @return value after transformed - */ - private Object setSingleField(Object[] tuple) { - if (tuple.length < 1) { - return null; - } - Object value = tuple[0]; - if (isPrimitive(mappedClass)) { - if (Character.class.isAssignableFrom(mappedClass)) { - throw new IllegalArgumentException("Not support Character!"); - } - for (Constructor constructor : mappedClass.getDeclaredConstructors()) { - try { - int count = constructor.getParameterCount(); - if (count == 1) { - if (String.class.isAssignableFrom(constructor.getParameterTypes()[0])) { - - if (Objects.isNull(value)) { - return null; - } else { - return constructor.newInstance(value.toString()); - } - } - } - } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) { - throw new RuntimeException(e); - } - } - } - if (String.class.equals(mappedClass)) { - if (Objects.isNull(value)) { - return null; - } else { - return value.toString(); - } - } + throw new RuntimeException(" Can not transfer for class " + mappedClass); + } - if (Date.class.equals(mappedClass)) { - if (value instanceof TIMESTAMP) { - return SqlDataHelper.extractDate(value); - } - return value; - } - - throw new RuntimeException(" Can not transfer for class " + mappedClass); + private static boolean isPrimitive(Class propertyType) { + if (propertyType.isPrimitive()) { + return true; } - - private static boolean isPrimitive(Class propertyType) { - - if (propertyType.isPrimitive()) { - return true; - } - if (Number.class.isAssignableFrom(propertyType)) { - return true; - } - try { - return ((Class) propertyType.getField("TYPE").get(null)).isPrimitive(); - } catch (Exception e) { - return false; - } + if (Number.class.isAssignableFrom(propertyType)) { + return true; } - + try { + return ((Class) propertyType.getField("TYPE").get(null)).isPrimitive(); + } catch (Exception e) { + return false; + } + } } diff --git a/src/main/java/com/sondertara/joya/hibernate/transformer/AliasToMapResultTransformer.java b/src/main/java/com/sondertara/joya/hibernate/transformer/AliasToMapResultTransformer.java index c8e6fe7..0c5e2b5 100644 --- a/src/main/java/com/sondertara/joya/hibernate/transformer/AliasToMapResultTransformer.java +++ b/src/main/java/com/sondertara/joya/hibernate/transformer/AliasToMapResultTransformer.java @@ -22,50 +22,52 @@ */ public class AliasToMapResultTransformer extends AliasedTupleSubsetResultTransformer { - public static ConcurrentHashMap TRANSFORMER = new ConcurrentHashMap(); + public static ConcurrentHashMap TRANSFORMER = + new ConcurrentHashMap(); - private final Boolean camelCase; + private final Boolean camelCase; - private AliasToMapResultTransformer(Boolean camelCase) { - this.camelCase = camelCase; - } + private AliasToMapResultTransformer(Boolean camelCase) { + this.camelCase = camelCase; + } - public static AliasToMapResultTransformer getInstance(Boolean camelCase) { + public static AliasToMapResultTransformer getInstance(Boolean camelCase) { - return TRANSFORMER.computeIfAbsent(camelCase.toString(), k -> new AliasToMapResultTransformer(camelCase)); - } + return TRANSFORMER.computeIfAbsent( + camelCase.toString(), k -> new AliasToMapResultTransformer(camelCase)); + } - @Override - public Object transformTuple(Object[] tuple, String[] aliases) { - Map result = new HashMap<>(tuple.length); - for (int i = 0; i < tuple.length; i++) { - String alias = aliases[i]; - if (alias != null) { - Object value = tuple[i]; - if (camelCase) { - int index = alias.indexOf("."); - if (index > -1) { - alias = alias.substring(index + 1); - } - alias = StringUtils.toCamelCase(alias); - } - if (null != value) { - if (SqlDataHelper.isClob(value.getClass())) { - value = SqlDataHelper.extractString((Clob) value); - } else if (Reader.class.isAssignableFrom(value.getClass())) { - value = SqlDataHelper.extractString((Reader) value); - } else if (value instanceof TIMESTAMP) { - value = SqlDataHelper.extractDate(value); - } - } - result.put(alias, value); - } + @Override + public Object transformTuple(Object[] tuple, String[] aliases) { + Map result = new HashMap<>(tuple.length); + for (int i = 0; i < tuple.length; i++) { + String alias = aliases[i]; + if (alias != null) { + Object value = tuple[i]; + if (camelCase) { + int index = alias.indexOf("."); + if (index > -1) { + alias = alias.substring(index + 1); + } + alias = StringUtils.toCamelCase(alias); } - return result; + if (null != value) { + if (SqlDataHelper.isClob(value.getClass())) { + value = SqlDataHelper.extractString((Clob) value); + } else if (Reader.class.isAssignableFrom(value.getClass())) { + value = SqlDataHelper.extractString((Reader) value); + } else if (value instanceof TIMESTAMP) { + value = SqlDataHelper.extractDate(value); + } + } + result.put(alias, value); + } } + return result; + } - @Override - public boolean isTransformedValueATupleElement(String[] aliases, int tupleLength) { - return false; - } + @Override + public boolean isTransformedValueATupleElement(String[] aliases, int tupleLength) { + return false; + } } diff --git a/src/main/java/com/sondertara/joya/hibernate/transformer/MappedFieldsInitializer.java b/src/main/java/com/sondertara/joya/hibernate/transformer/MappedFieldsInitializer.java index f8f2c31..9e45d6d 100644 --- a/src/main/java/com/sondertara/joya/hibernate/transformer/MappedFieldsInitializer.java +++ b/src/main/java/com/sondertara/joya/hibernate/transformer/MappedFieldsInitializer.java @@ -14,44 +14,43 @@ */ public class MappedFieldsInitializer { - private static boolean isMap(Class propertyType) { - return Map.class.isAssignableFrom(propertyType); + private static boolean isMap(Class propertyType) { + return Map.class.isAssignableFrom(propertyType); + } + + private static boolean isPrimitive(Class propertyType) { + return Number.class.isAssignableFrom(propertyType) + || propertyType.isPrimitive() + || String.class.isAssignableFrom(propertyType) + || Date.class.isAssignableFrom(propertyType); + } + + public Map init(Class mappedClass) { + Map fields = Maps.newHashMap(); + PropertyDescriptor[] pds = BeanUtils.getPropertyDescriptors(mappedClass); + for (PropertyDescriptor pd : pds) { + if (pd.getWriteMethod() == null) { + continue; + } + + Class propertyType = pd.getPropertyType(); + String name = pd.getName(); + + if (isPrimitive(propertyType)) { + fields.put(name, new Fields(pd)); + continue; + } + + if (isMap(propertyType)) { + fields.put(name, new MapFields(pd)); + continue; + } + + Fields childField = new Fields(pd); + + childField.setChildrenFields(init(propertyType)); + fields.put(name, childField); } - - private static boolean isPrimitive(Class propertyType) { - return Number.class.isAssignableFrom(propertyType) || - propertyType.isPrimitive() || - String.class.isAssignableFrom(propertyType) || - Date.class.isAssignableFrom(propertyType); - } - - public Map init(Class mappedClass) { - Map fields = Maps.newHashMap(); - PropertyDescriptor[] pds = BeanUtils.getPropertyDescriptors(mappedClass); - for (PropertyDescriptor pd : pds) { - if (pd.getWriteMethod() == null) { - continue; - } - - Class propertyType = pd.getPropertyType(); - String name = pd.getName(); - - if (isPrimitive(propertyType)) { - fields.put(name, new Fields(pd)); - continue; - } - - if (isMap(propertyType)) { - fields.put(name, new MapFields(pd)); - continue; - } - - Fields childField = new Fields(pd); - - childField.setChildrenFields(init(propertyType)); - fields.put(name, childField); - } - return fields; - } - + return fields; + } } diff --git a/src/main/java/com/sondertara/joya/hibernate/transformer/ValueSetter.java b/src/main/java/com/sondertara/joya/hibernate/transformer/ValueSetter.java index 5662983..e9819d1 100644 --- a/src/main/java/com/sondertara/joya/hibernate/transformer/ValueSetter.java +++ b/src/main/java/com/sondertara/joya/hibernate/transformer/ValueSetter.java @@ -19,78 +19,76 @@ */ public class ValueSetter { - protected static DefaultConversionService conversionService; + protected static DefaultConversionService conversionService; - static { - ValueSetter.conversionService = new DefaultConversionService(); - Collection> convertersToRegister = Jsr310Converters.getConvertersToRegister(); - for (Converter converter : convertersToRegister) { - ValueSetter.conversionService.addConverter(converter); - } + static { + ValueSetter.conversionService = new DefaultConversionService(); + Collection> convertersToRegister = Jsr310Converters.getConvertersToRegister(); + for (Converter converter : convertersToRegister) { + ValueSetter.conversionService.addConverter(converter); } - - private final Map genericMap = new HashMap<>(); - - public static BeanWrapper getBeanWrapper(Object instantiate) { - BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(instantiate); - bw.setConversionService(conversionService); - return bw; + } + + private final Map genericMap = new HashMap<>(); + + public static BeanWrapper getBeanWrapper(Object instantiate) { + BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(instantiate); + bw.setConversionService(conversionService); + return bw; + } + + public void set( + Object instantiate, String alias, Object value, Map mappedFields) { + BeanWrapper beanWrapper = getBeanWrapper(instantiate); + if (!alias.contains(ALIAS_SPLIT)) { + Fields field = mappedFields.get(alias); + if (null == field) { + return; + } + field.setResultPropertyValue(beanWrapper, instantiate, alias, value); + return; } - public void set(Object instantiate, String alias, Object value, Map mappedFields) { - BeanWrapper beanWrapper = getBeanWrapper(instantiate); - if (!alias.contains(ALIAS_SPLIT)) { - Fields field = mappedFields.get(alias); - if (null == field) { - return; - } - field.setResultPropertyValue(beanWrapper, instantiate, alias, value); - return; - } - - - int index = alias.indexOf(ALIAS_SPLIT); - String alias2 = alias.substring(0, index); - String remainAlias = alias.substring(index + 1); + int index = alias.indexOf(ALIAS_SPLIT); + String alias2 = alias.substring(0, index); + String remainAlias = alias.substring(index + 1); - Fields field = mappedFields.get(alias2); - if (null == field) { - return; - } - Object propertyValue = beanWrapper.getPropertyValue(field.getName()); - if (propertyValue == null) { - propertyValue = field.instantiateObjectValue(); - field.setObjectPropertyValue(beanWrapper, propertyValue); - } - - if (field.isMap()) { - if (remainAlias.contains(ALIAS_SPLIT)) { - throw new RuntimeException("Map对象结果只能嵌入一层,不能嵌入多层,alias:" + alias); - } - field.setResultPropertyValue(null, propertyValue, remainAlias, value); - return; - } - - set(propertyValue, remainAlias, value, field.getChildrenFields()); + Fields field = mappedFields.get(alias2); + if (null == field) { + return; } - - @SuppressWarnings({"unchecked", "rawtypes"}) - private Object getGenericObject(Object propertyValue, CollectionFields collectionFields) { - String name = collectionFields.getName(); - Object o = this.genericMap.get(name); - if (o != null) { - return o; - } - Collection collection = (Collection) propertyValue; - Object instantiate = collectionFields.instantiateGenericObject(); - collection.add(instantiate); - this.genericMap.put(name, instantiate); - return instantiate; + Object propertyValue = beanWrapper.getPropertyValue(field.getName()); + if (propertyValue == null) { + propertyValue = field.instantiateObjectValue(); + field.setObjectPropertyValue(beanWrapper, propertyValue); } - public void clearGenericMap() { - this.genericMap.clear(); + if (field.isMap()) { + if (remainAlias.contains(ALIAS_SPLIT)) { + throw new RuntimeException("Map对象结果只能嵌入一层,不能嵌入多层,alias:" + alias); + } + field.setResultPropertyValue(null, propertyValue, remainAlias, value); + return; } + set(propertyValue, remainAlias, value, field.getChildrenFields()); + } + @SuppressWarnings({"unchecked", "rawtypes"}) + private Object getGenericObject(Object propertyValue, CollectionFields collectionFields) { + String name = collectionFields.getName(); + Object o = this.genericMap.get(name); + if (o != null) { + return o; + } + Collection collection = (Collection) propertyValue; + Object instantiate = collectionFields.instantiateGenericObject(); + collection.add(instantiate); + this.genericMap.put(name, instantiate); + return instantiate; + } + + public void clearGenericMap() { + this.genericMap.clear(); + } } diff --git a/src/main/java/com/sondertara/joya/hibernate/transformer/mappedfileds/CollectionFields.java b/src/main/java/com/sondertara/joya/hibernate/transformer/mappedfileds/CollectionFields.java index 3822862..c428cd8 100644 --- a/src/main/java/com/sondertara/joya/hibernate/transformer/mappedfileds/CollectionFields.java +++ b/src/main/java/com/sondertara/joya/hibernate/transformer/mappedfileds/CollectionFields.java @@ -17,44 +17,41 @@ * @author huangxiaohu */ public class CollectionFields extends Fields { - private final Class genericClass; - - public CollectionFields(PropertyDescriptor propertyDescriptor, Class genericClass) { - super(propertyDescriptor); - this.genericClass = genericClass; - } - - @Override - public boolean isCollection() { - return true; + private final Class genericClass; + + public CollectionFields(PropertyDescriptor propertyDescriptor, Class genericClass) { + super(propertyDescriptor); + this.genericClass = genericClass; + } + + @Override + public boolean isCollection() { + return true; + } + + @Override + public void setResultPropertyValue( + BeanWrapper bw, Object instantiate, String name, Object value) {} + + @Override + public Object instantiateObjectValue() { + Class propertyType = this.propertyDescriptor.getPropertyType(); + if (propertyType.isAssignableFrom(Set.class)) { + return new HashSet<>(); + } else if (propertyType.isAssignableFrom(List.class)) { + return new ArrayList<>(); } + throw new RuntimeException("只支持两种集合类型:Set,List"); + } - @Override - public void setResultPropertyValue(BeanWrapper bw, Object instantiate, String name, Object value) { + public Class getGenericClass() { + return genericClass; + } + public Object instantiateGenericObject() { + if (this.genericClass.isAssignableFrom(Map.class)) { + return new HashMap<>(); } - - @Override - public Object instantiateObjectValue() { - Class propertyType = this.propertyDescriptor.getPropertyType(); - if (propertyType.isAssignableFrom(Set.class)) { - return new HashSet<>(); - } else if (propertyType.isAssignableFrom(List.class)) { - return new ArrayList<>(); - } - throw new RuntimeException("只支持两种集合类型:Set,List"); - } - - public Class getGenericClass() { - return genericClass; - } - - - public Object instantiateGenericObject() { - if (this.genericClass.isAssignableFrom(Map.class)) { - return new HashMap<>(); - } - return BeanUtils.instantiateClass(this.genericClass); - } - + return BeanUtils.instantiateClass(this.genericClass); + } } diff --git a/src/main/java/com/sondertara/joya/hibernate/transformer/mappedfileds/Fields.java b/src/main/java/com/sondertara/joya/hibernate/transformer/mappedfileds/Fields.java index b062307..43c7ce0 100644 --- a/src/main/java/com/sondertara/joya/hibernate/transformer/mappedfileds/Fields.java +++ b/src/main/java/com/sondertara/joya/hibernate/transformer/mappedfileds/Fields.java @@ -10,67 +10,68 @@ * @author huangxiaohu */ public class Fields { - protected String name; - protected PropertyDescriptor propertyDescriptor; - protected Map childrenFields; - - public Fields(PropertyDescriptor propertyDescriptor) { - this(propertyDescriptor, null); - } - - public Fields(PropertyDescriptor propertyDescriptor, Map childrenFields) { - this.name = propertyDescriptor.getName(); - this.propertyDescriptor = propertyDescriptor; - this.childrenFields = childrenFields; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public PropertyDescriptor getPropertyDescriptor() { - return propertyDescriptor; - } - - public void setPropertyDescriptor(PropertyDescriptor propertyDescriptor) { - this.propertyDescriptor = propertyDescriptor; - } - - public Map getChildrenFields() { - return childrenFields; + protected String name; + protected PropertyDescriptor propertyDescriptor; + protected Map childrenFields; + + public Fields(PropertyDescriptor propertyDescriptor) { + this(propertyDescriptor, null); + } + + public Fields(PropertyDescriptor propertyDescriptor, Map childrenFields) { + this.name = propertyDescriptor.getName(); + this.propertyDescriptor = propertyDescriptor; + this.childrenFields = childrenFields; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public PropertyDescriptor getPropertyDescriptor() { + return propertyDescriptor; + } + + public void setPropertyDescriptor(PropertyDescriptor propertyDescriptor) { + this.propertyDescriptor = propertyDescriptor; + } + + public Map getChildrenFields() { + return childrenFields; + } + + public void setChildrenFields(Map childrenFields) { + this.childrenFields = childrenFields; + } + + public Class getPropertyType() { + return this.propertyDescriptor.getPropertyType(); + } + + public Object instantiateObjectValue() { + return BeanUtils.instantiateClass(getPropertyType()); + } + + public boolean isMap() { + return false; + } + + public boolean isCollection() { + return false; + } + + public void setResultPropertyValue( + BeanWrapper bw, Object instantiate, String name, Object value) { + if (value != null) { + bw.setPropertyValue(this.name, value); } + } - public void setChildrenFields(Map childrenFields) { - this.childrenFields = childrenFields; - } - - public Class getPropertyType() { - return this.propertyDescriptor.getPropertyType(); - } - - public Object instantiateObjectValue() { - return BeanUtils.instantiateClass(getPropertyType()); - } - - public boolean isMap() { - return false; - } - - public boolean isCollection() { - return false; - } - - public void setResultPropertyValue(BeanWrapper bw, Object instantiate, String name, Object value) { - if (value != null) { - bw.setPropertyValue(this.name, value); - } - } - - public void setObjectPropertyValue(BeanWrapper bw, Object propertyValue) { - bw.setPropertyValue(this.name, propertyValue); - } + public void setObjectPropertyValue(BeanWrapper bw, Object propertyValue) { + bw.setPropertyValue(this.name, propertyValue); + } } diff --git a/src/main/java/com/sondertara/joya/hibernate/transformer/mappedfileds/MapFields.java b/src/main/java/com/sondertara/joya/hibernate/transformer/mappedfileds/MapFields.java index 27467ca..a951808 100644 --- a/src/main/java/com/sondertara/joya/hibernate/transformer/mappedfileds/MapFields.java +++ b/src/main/java/com/sondertara/joya/hibernate/transformer/mappedfileds/MapFields.java @@ -10,27 +10,25 @@ * @author SonderTara */ public class MapFields extends Fields { - public MapFields(PropertyDescriptor propertyDescriptor) { - super(propertyDescriptor); - } - - - @Override - public boolean isMap() { - return true; - } - - @Override - @SuppressWarnings({"unchecked", "rawtypes"}) - public void setResultPropertyValue(BeanWrapper bw, Object instantiate, String name, Object value) { - Map map = (Map) instantiate; - map.put(name, value); - } - - @Override - public Object instantiateObjectValue() { - return new HashMap<>(); - } - - + public MapFields(PropertyDescriptor propertyDescriptor) { + super(propertyDescriptor); + } + + @Override + public boolean isMap() { + return true; + } + + @Override + @SuppressWarnings({"unchecked", "rawtypes"}) + public void setResultPropertyValue( + BeanWrapper bw, Object instantiate, String name, Object value) { + Map map = (Map) instantiate; + map.put(name, value); + } + + @Override + public Object instantiateObjectValue() { + return new HashMap<>(); + } } diff --git a/src/main/java/com/sondertara/joya/hibernate/type/CollectionToStringUserType.java b/src/main/java/com/sondertara/joya/hibernate/type/CollectionToStringUserType.java index 5f7cc34..7585ea0 100644 --- a/src/main/java/com/sondertara/joya/hibernate/type/CollectionToStringUserType.java +++ b/src/main/java/com/sondertara/joya/hibernate/type/CollectionToStringUserType.java @@ -1,6 +1,5 @@ package com.sondertara.joya.hibernate.type; - import com.sondertara.common.util.StringUtils; import org.apache.commons.beanutils.ConvertUtils; import org.hibernate.HibernateException; @@ -19,202 +18,190 @@ import java.util.Properties; /** - * 将List转换为指定分隔符分隔的字符串存储 List的元素类型只支持常见的数据类型 可参考{@link org.apache.commons.beanutils.ConvertUtilsBean} + * 将List转换为指定分隔符分隔的字符串存储 List的元素类型只支持常见的数据类型 可参考{@link + * org.apache.commons.beanutils.ConvertUtilsBean} * * @author Wu Tianqiang */ public class CollectionToStringUserType implements UserType, ParameterizedType, Serializable { - /** - * 默认, - */ - private String separator; - /** - * 默认 java.lang.Long - */ - @SuppressWarnings("rawtypes") - private Class elementType; - /** - * 默认 ArrayList - */ - private Class collectionType; - - - @Override - public void setParameterValues(Properties parameters) { - String separator = (String) parameters.get("separator"); - if (!StringUtils.isEmpty(separator)) { - this.separator = separator; - } else { - this.separator = ","; - } - - String collectionType = (String) parameters.get("collectionType"); - if (!StringUtils.isEmpty(collectionType)) { - try { - this.collectionType = Class.forName(collectionType); - } catch (ClassNotFoundException e) { - throw new HibernateException(e); - } - } else { - this.collectionType = java.util.ArrayList.class; - } - - String elementType = (String) parameters.get("elementType"); - if (!StringUtils.isEmpty(elementType)) { - try { - this.elementType = Class.forName(elementType); - } catch (ClassNotFoundException e) { - throw new HibernateException(e); - } - } else { - this.elementType = Long.TYPE; - } + /** 默认, */ + private String separator; + /** 默认 java.lang.Long */ + @SuppressWarnings("rawtypes") + private Class elementType; + /** 默认 ArrayList */ + private Class collectionType; + + @Override + public void setParameterValues(Properties parameters) { + String separator = (String) parameters.get("separator"); + if (!StringUtils.isEmpty(separator)) { + this.separator = separator; + } else { + this.separator = ","; } - @Override - public int[] sqlTypes() { - return new int[]{Types.VARCHAR}; + String collectionType = (String) parameters.get("collectionType"); + if (!StringUtils.isEmpty(collectionType)) { + try { + this.collectionType = Class.forName(collectionType); + } catch (ClassNotFoundException e) { + throw new HibernateException(e); + } + } else { + this.collectionType = java.util.ArrayList.class; } - @Override - @SuppressWarnings("rawtypes") - public Class returnedClass() { - return collectionType; + String elementType = (String) parameters.get("elementType"); + if (!StringUtils.isEmpty(elementType)) { + try { + this.elementType = Class.forName(elementType); + } catch (ClassNotFoundException e) { + throw new HibernateException(e); + } + } else { + this.elementType = Long.TYPE; } - - @Override - public boolean equals(Object o, Object o1) throws HibernateException { - return Objects.equals(o, o1); - - } - - @Override - public int hashCode(Object o) throws HibernateException { - return o.hashCode(); + } + + @Override + public int[] sqlTypes() { + return new int[] {Types.VARCHAR}; + } + + @Override + @SuppressWarnings("rawtypes") + public Class returnedClass() { + return collectionType; + } + + @Override + public boolean equals(Object o, Object o1) throws HibernateException { + return Objects.equals(o, o1); + } + + @Override + public int hashCode(Object o) throws HibernateException { + return o.hashCode(); + } + + /** + * 从JDBC ResultSet读取数据,将其转换为自定义类型后返回 (此方法要求对克能出现null值进行处理) names中包含了当前自定义类型的映射字段名称 + * + * @param names names + * @param owner owner + * @throws HibernateException e + * @throws SQLException e + */ + @Override + @SuppressWarnings({"rawtypes", "unchecked"}) + public Object nullSafeGet( + ResultSet resultSet, String[] names, SharedSessionContractImplementor session, Object owner) + throws HibernateException, SQLException { + String valueStr = resultSet.getString(names[0]); + if (StringUtils.isEmpty(valueStr)) { + return newCollection(); } - - - /** - * 从JDBC ResultSet读取数据,将其转换为自定义类型后返回 - * (此方法要求对克能出现null值进行处理) - * names中包含了当前自定义类型的映射字段名称 - * - * @param names names - * @param owner owner - * @throws HibernateException e - * @throws SQLException e - */ - @Override - @SuppressWarnings({"rawtypes", "unchecked"}) - public Object nullSafeGet(ResultSet resultSet, String[] names, SharedSessionContractImplementor session, Object owner) throws HibernateException, SQLException { - String valueStr = resultSet.getString(names[0]); - if (StringUtils.isEmpty(valueStr)) { - return newCollection(); - } - String[] values = StringUtils.split(valueStr, separator); - Collection result = newCollection(); - for (String value : values) { - if (StringUtils.isNotEmpty(value)) { - if (Persistable.class.isAssignableFrom(this.elementType)) { - Integer id = Integer.valueOf(value); - Object obj = session.immediateLoad(this.elementType.getName(), id); - result.add(ConvertUtils.convert(obj, elementType)); - } else { - result.add(ConvertUtils.convert(value, elementType)); - } - } - } - return result; - } - - @SuppressWarnings("rawtypes") - private Collection newCollection() { - try { - return (Collection) collectionType.getDeclaredConstructor().newInstance(); - } catch (Exception e) { - throw new HibernateException(e); - } - } - - /** - * 本方法将在Hibernate进行数据保存时被调用 - * 我们可以通过PreparedStatement将自定义数据写入到对应的数据库表字段 - */ - @SuppressWarnings("rawtypes") - @Override - public void nullSafeSet(PreparedStatement preparedStatement, Object value, int index, SharedSessionContractImplementor sharedSessionContractImplementor) throws HibernateException, SQLException { - String valueStr; - if (value == null) { - valueStr = ""; + String[] values = StringUtils.split(valueStr, separator); + Collection result = newCollection(); + for (String value : values) { + if (StringUtils.isNotEmpty(value)) { + if (Persistable.class.isAssignableFrom(this.elementType)) { + Integer id = Integer.valueOf(value); + Object obj = session.immediateLoad(this.elementType.getName(), id); + result.add(ConvertUtils.convert(obj, elementType)); } else { - valueStr = join((Collection) value, separator); - } - preparedStatement.setString(index, valueStr); - } - - @SuppressWarnings("rawtypes") - private String join(Collection value, String separator) { - StringBuilder sb = new StringBuilder(); - for (Object o : value) { - if (o instanceof Persistable) { - sb.append(((Persistable) o).getId()); - } else { - sb.append(o); - } - sb.append(separator); + result.add(ConvertUtils.convert(value, elementType)); } - if (sb.length() > 1) { - sb.deleteCharAt(sb.length() - 1); - } - return sb.toString(); + } } - - /** - * 提供自定义类型的完全复制方法 - * 本方法将用构造返回对象 - * 当nullSafeGet方法调用之后,我们获得了自定义数据对象,在向用户返回自定义数据之前, - * deepCopy方法将被调用,它将根据自定义数据对象构造一个完全拷贝,并将此拷贝返回给用户 - * 此时我们就得到了自定义数据对象的两个版本,第一个是从数据库读出的原始版本,其二是我们通过 - * deepCopy方法构造的复制版本,原始的版本将有Hibernate维护,复制版由用户使用。原始版本用作 - * 稍后的脏数据检查依据;Hibernate将在脏数据检查过程中将两个版本的数据进行对比(通过调用 - * equals方法),如果数据发生了变化(equals方法返回false),则执行对应的持久化操作 - * - * @param o object - * @throws HibernateException e - */ - @Override - @SuppressWarnings({"unchecked", "rawtypes"}) - public Object deepCopy(Object o) throws HibernateException { - if (o == null) { - return null; - } - Collection copyCollection = newCollection(); - copyCollection.addAll((Collection) o); - return copyCollection; + return result; + } + + @SuppressWarnings("rawtypes") + private Collection newCollection() { + try { + return (Collection) collectionType.getDeclaredConstructor().newInstance(); + } catch (Exception e) { + throw new HibernateException(e); } - - /** - * 本类型实例是否可变 - */ - @Override - public boolean isMutable() { - return true; + } + + /** 本方法将在Hibernate进行数据保存时被调用 我们可以通过PreparedStatement将自定义数据写入到对应的数据库表字段 */ + @SuppressWarnings("rawtypes") + @Override + public void nullSafeSet( + PreparedStatement preparedStatement, + Object value, + int index, + SharedSessionContractImplementor sharedSessionContractImplementor) + throws HibernateException, SQLException { + String valueStr; + if (value == null) { + valueStr = ""; + } else { + valueStr = join((Collection) value, separator); } - - @Override - public Serializable disassemble(Object value) throws HibernateException { - return ((Serializable) value); + preparedStatement.setString(index, valueStr); + } + + @SuppressWarnings("rawtypes") + private String join(Collection value, String separator) { + StringBuilder sb = new StringBuilder(); + for (Object o : value) { + if (o instanceof Persistable) { + sb.append(((Persistable) o).getId()); + } else { + sb.append(o); + } + sb.append(separator); } - - @Override - public Object assemble(Serializable cached, Object owner) throws HibernateException { - return cached; + if (sb.length() > 1) { + sb.deleteCharAt(sb.length() - 1); } - - @Override - public Object replace(Object original, Object target, Object owner) throws HibernateException { - return original; + return sb.toString(); + } + + /** + * 提供自定义类型的完全复制方法 本方法将用构造返回对象 当nullSafeGet方法调用之后,我们获得了自定义数据对象,在向用户返回自定义数据之前, + * deepCopy方法将被调用,它将根据自定义数据对象构造一个完全拷贝,并将此拷贝返回给用户 此时我们就得到了自定义数据对象的两个版本,第一个是从数据库读出的原始版本,其二是我们通过 + * deepCopy方法构造的复制版本,原始的版本将有Hibernate维护,复制版由用户使用。原始版本用作 + * 稍后的脏数据检查依据;Hibernate将在脏数据检查过程中将两个版本的数据进行对比(通过调用 + * equals方法),如果数据发生了变化(equals方法返回false),则执行对应的持久化操作 + * + * @param o object + * @throws HibernateException e + */ + @Override + @SuppressWarnings({"unchecked", "rawtypes"}) + public Object deepCopy(Object o) throws HibernateException { + if (o == null) { + return null; } - + Collection copyCollection = newCollection(); + copyCollection.addAll((Collection) o); + return copyCollection; + } + + /** 本类型实例是否可变 */ + @Override + public boolean isMutable() { + return true; + } + + @Override + public Serializable disassemble(Object value) throws HibernateException { + return ((Serializable) value); + } + + @Override + public Object assemble(Serializable cached, Object owner) throws HibernateException { + return cached; + } + + @Override + public Object replace(Object original, Object target, Object owner) throws HibernateException { + return original; + } } diff --git a/src/main/java/com/sondertara/joya/hibernate/type/JsonType.java b/src/main/java/com/sondertara/joya/hibernate/type/JsonType.java index b88f7ce..8217fef 100644 --- a/src/main/java/com/sondertara/joya/hibernate/type/JsonType.java +++ b/src/main/java/com/sondertara/joya/hibernate/type/JsonType.java @@ -33,206 +33,216 @@ * @author huangxiaohu */ public class JsonType implements UserType, DynamicParameterizedType, Serializable { - public static final String TYPE = "JSONType"; - public static final String CLASS_NAME = "class"; - private static final long serialVersionUID = 352044032843534075L; - private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, JsonType.class.getName()); - private int sqlType = Types.VARCHAR; - private Type type = Object.class; - - private static String extractString(Object value) { - if (value == null) { - return null; - } - if (value instanceof String) { - return (String) value; - } - if (value instanceof Reader) { - return DataHelper.extractString((Reader) value); - } - if (value instanceof Clob) { - return DataHelper.extractString((Clob) value); - } - return null; + public static final String TYPE = "JSONType"; + public static final String CLASS_NAME = "class"; + private static final long serialVersionUID = 352044032843534075L; + private static final CoreMessageLogger LOG = + Logger.getMessageLogger(CoreMessageLogger.class, JsonType.class.getName()); + private int sqlType = Types.VARCHAR; + private Type type = Object.class; + + private static String extractString(Object value) { + if (value == null) { + return null; } - - @Override - public int[] sqlTypes() { - return new int[]{sqlType}; + if (value instanceof String) { + return (String) value; } - - @Override - @SuppressWarnings("rawtypes") - public Class returnedClass() { - if (type instanceof ParameterizedType) { - return (Class) ((ParameterizedType) type).getRawType(); - } else { - return (Class) type; - } + if (value instanceof Reader) { + return DataHelper.extractString((Reader) value); } - - @Override - public boolean equals(Object x, Object y) throws HibernateException { - return Objects.equals(x, y); + if (value instanceof Clob) { + return DataHelper.extractString((Clob) value); } - - @Override - public int hashCode(Object x) throws HibernateException { - return x.hashCode(); + return null; + } + + @Override + public int[] sqlTypes() { + return new int[] {sqlType}; + } + + @Override + @SuppressWarnings("rawtypes") + public Class returnedClass() { + if (type instanceof ParameterizedType) { + return (Class) ((ParameterizedType) type).getRawType(); + } else { + return (Class) type; } - - /** - * 从JDBC ResultSet读取数据,将其转换为自定义类型后返回 - * (此方法要求对可能出现null值进行处理) - * names中包含了当前自定义类型的映射字段名称 - * - * @param rs result - * @param names list - * @param owner owner - * @return obj - * @throws HibernateException e - * @throws SQLException e - */ - @Override - public Object nullSafeGet(ResultSet rs, String[] names, SharedSessionContractImplementor sharedSessionContractImplementor, Object owner) throws HibernateException, SQLException { - String value = extractString(rs.getObject(names[0])); - if (rs.wasNull() || StringUtils.isEmpty(value)) { - if (LOG.isTraceEnabled()) { - LOG.tracev("Returning null as column {0}", names[0]); - } - return null; - } else if (type == Object.class) { - return JSON.parse(value); - } else { - return JSON.parseObject(value, type); - } + } + + @Override + public boolean equals(Object x, Object y) throws HibernateException { + return Objects.equals(x, y); + } + + @Override + public int hashCode(Object x) throws HibernateException { + return x.hashCode(); + } + + /** + * 从JDBC ResultSet读取数据,将其转换为自定义类型后返回 (此方法要求对可能出现null值进行处理) names中包含了当前自定义类型的映射字段名称 + * + * @param rs result + * @param names list + * @param owner owner + * @return obj + * @throws HibernateException e + * @throws SQLException e + */ + @Override + public Object nullSafeGet( + ResultSet rs, + String[] names, + SharedSessionContractImplementor sharedSessionContractImplementor, + Object owner) + throws HibernateException, SQLException { + String value = extractString(rs.getObject(names[0])); + if (rs.wasNull() || StringUtils.isEmpty(value)) { + if (LOG.isTraceEnabled()) { + LOG.tracev("Returning null as column {0}", names[0]); + } + return null; + } else if (type == Object.class) { + return JSON.parse(value); + } else { + return JSON.parseObject(value, type); } - - /** - * 本方法将在Hibernate进行数据保存时被调用 - * 我们可以通过PreparedStatement将自定义数据写入到对应的数据库表字段 - * - * @param st statement - * @param value v - * @param index index - * @throws HibernateException e - * @throws SQLException e - */ - @Override - public void nullSafeSet(PreparedStatement st, Object value, int index, SharedSessionContractImplementor sharedSessionContractImplementor) throws HibernateException, SQLException { - if (value == null) { - if (LOG.isTraceEnabled()) { - LOG.tracev("Binding null to parameter: {0}", index); - } - st.setNull(index, sqlType); - } else { - String json; - if (type == Object.class) { - json = JSON.toJSONString(value, SerializerFeature.WriteClassName); - } else { - json = JSON.toJSONString(value); - } - if (sqlType == Types.CLOB) { - StringReader sr = new StringReader(json); - st.setCharacterStream(index, sr, json.length()); - } else { - st.setObject(index, json, sqlType); - } - } + } + + /** + * 本方法将在Hibernate进行数据保存时被调用 我们可以通过PreparedStatement将自定义数据写入到对应的数据库表字段 + * + * @param st statement + * @param value v + * @param index index + * @throws HibernateException e + * @throws SQLException e + */ + @Override + public void nullSafeSet( + PreparedStatement st, + Object value, + int index, + SharedSessionContractImplementor sharedSessionContractImplementor) + throws HibernateException, SQLException { + if (value == null) { + if (LOG.isTraceEnabled()) { + LOG.tracev("Binding null to parameter: {0}", index); + } + st.setNull(index, sqlType); + } else { + String json; + if (type == Object.class) { + json = JSON.toJSONString(value, SerializerFeature.WriteClassName); + } else { + json = JSON.toJSONString(value); + } + if (sqlType == Types.CLOB) { + StringReader sr = new StringReader(json); + st.setCharacterStream(index, sr, json.length()); + } else { + st.setObject(index, json, sqlType); + } } - - /** - * 提供自定义类型的完全复制方法 - * 本方法将用构造返回对象 - * 当nullSafeGet方法调用之后,我们获得了自定义数据对象,在向用户返回自定义数据之前, - * deepCopy方法将被调用,它将根据自定义数据对象构造一个完全拷贝,并将此拷贝返回给用户 - * 此时我们就得到了自定义数据对象的两个版本,第一个是从数据库读出的原始版本,其二是我们通过 - * deepCopy方法构造的复制版本,原始的版本将有Hibernate维护,复制版由用户使用。原始版本用作 - * 稍后的脏数据检查依据;Hibernate将在脏数据检查过程中将两个版本的数据进行对比(通过调用 - * equals方法),如果数据发生了变化(equals方法返回false),则执行对应的持久化操作 - * - * @param value v - * @return object - * @throws HibernateException e - */ - @Override - public Object deepCopy(Object value) throws HibernateException { + } + + /** + * 提供自定义类型的完全复制方法 本方法将用构造返回对象 当nullSafeGet方法调用之后,我们获得了自定义数据对象,在向用户返回自定义数据之前, + * deepCopy方法将被调用,它将根据自定义数据对象构造一个完全拷贝,并将此拷贝返回给用户 此时我们就得到了自定义数据对象的两个版本,第一个是从数据库读出的原始版本,其二是我们通过 + * deepCopy方法构造的复制版本,原始的版本将有Hibernate维护,复制版由用户使用。原始版本用作 + * 稍后的脏数据检查依据;Hibernate将在脏数据检查过程中将两个版本的数据进行对比(通过调用 + * equals方法),如果数据发生了变化(equals方法返回false),则执行对应的持久化操作 + * + * @param value v + * @return object + * @throws HibernateException e + */ + @Override + public Object deepCopy(Object value) throws HibernateException { + return value; + /*if (value instanceof JSONObject) { + return ((JSONObject) value).clone(); + } else if (value instanceof Cloneable) { + return ObjectUtils.clone(value); + } else if (value instanceof Serializable) { + return SerializationHelper.clone((Serializable) value); + } else { return value; - /*if (value instanceof JSONObject) { - return ((JSONObject) value).clone(); - } else if (value instanceof Cloneable) { - return ObjectUtils.clone(value); - } else if (value instanceof Serializable) { - return SerializationHelper.clone((Serializable) value); - } else { - return value; - }*/ - } - - /** - * 本类型实例是否可变 - * - * @return is mutable - */ - @Override - public boolean isMutable() { - return true; + }*/ + } + + /** + * 本类型实例是否可变 + * + * @return is mutable + */ + @Override + public boolean isMutable() { + return true; + } + + @Override + public Serializable disassemble(Object value) throws HibernateException { + return (Serializable) value; + } + + @Override + public Object assemble(Serializable cached, Object owner) throws HibernateException { + return cached; + } + + @Override + public Object replace(Object original, Object target, Object owner) throws HibernateException { + return original; + } + + @Override + @SuppressWarnings({"rawtypes", "deprecated"}) + public void setParameterValues(Properties parameters) { + try { + Class eClass = + ReflectHelper.classForName( + parameters.getProperty(DynamicParameterizedType.ENTITY), this.getClass()); + Field field = + ReflectionUtils.findField( + eClass, parameters.getProperty(DynamicParameterizedType.PROPERTY)); + assert field != null; + Type fieldType = field.getGenericType(); + if (fieldType instanceof Class || fieldType instanceof ParameterizedType) { + type = fieldType; + } + parseSqlType(field.getAnnotations()); + return; + } catch (Exception e) { + LOG.error(e.getMessage()); } - - @Override - public Serializable disassemble(Object value) throws HibernateException { - return (Serializable) value; + // final ParameterType reader = (ParameterType) parameters.get( + final ParameterType reader = + (ParameterType) parameters.get(DynamicParameterizedType.PARAMETER_TYPE); + if (reader != null) { + type = reader.getReturnedClass(); + parseSqlType(reader.getAnnotationsMethod()); + } else { + try { + type = org.apache.commons.lang3.ClassUtils.getClass((String) parameters.get(CLASS_NAME)); + } catch (ClassNotFoundException exception) { + throw new HibernateException("class not found", exception); + } } - - @Override - public Object assemble(Serializable cached, Object owner) throws HibernateException { - return cached; - } - - @Override - public Object replace(Object original, Object target, Object owner) throws HibernateException { - return original; - } - - @Override - @SuppressWarnings({"rawtypes", "deprecated"}) - public void setParameterValues(Properties parameters) { - try { - Class eClass = ReflectHelper.classForName(parameters.getProperty(DynamicParameterizedType.ENTITY), this.getClass()); - Field field = ReflectionUtils.findField(eClass, parameters.getProperty(DynamicParameterizedType.PROPERTY)); - assert field != null; - Type fieldType = field.getGenericType(); - if (fieldType instanceof Class || fieldType instanceof ParameterizedType) { - type = fieldType; - } - parseSqlType(field.getAnnotations()); - return; - } catch (Exception e) { - LOG.error(e.getMessage()); - } - //final ParameterType reader = (ParameterType) parameters.get( - final ParameterType reader = (ParameterType) parameters.get(DynamicParameterizedType.PARAMETER_TYPE); - if (reader != null) { - type = reader.getReturnedClass(); - parseSqlType(reader.getAnnotationsMethod()); - } else { - try { - type = org.apache.commons.lang3.ClassUtils.getClass((String) parameters.get(CLASS_NAME)); - } catch (ClassNotFoundException exception) { - throw new HibernateException("class not found", exception); - } - } - } - - private void parseSqlType(Annotation[] annotations) { - for (Annotation an : annotations) { - if (an instanceof Column) { - int length = ((Column) an).length(); - if (length > 4000) { - sqlType = Types.CLOB; - } - break; - } + } + + private void parseSqlType(Annotation[] annotations) { + for (Annotation an : annotations) { + if (an instanceof Column) { + int length = ((Column) an).length(); + if (length > 4000) { + sqlType = Types.CLOB; } + break; + } } + } } diff --git a/src/main/java/com/sondertara/joya/init/BaseRepositoryFactory.java b/src/main/java/com/sondertara/joya/init/BaseRepositoryFactory.java index 93771da..301c2de 100644 --- a/src/main/java/com/sondertara/joya/init/BaseRepositoryFactory.java +++ b/src/main/java/com/sondertara/joya/init/BaseRepositoryFactory.java @@ -13,47 +13,46 @@ import javax.persistence.EntityManager; import java.io.Serializable; - /** * @author huangxiaohu */ public class BaseRepositoryFactory extends JpaRepositoryFactory { - private EntityManager entityManager; - private PersistenceProvider extractor; - - - public BaseRepositoryFactory(EntityManager entityManager) { - super(entityManager); - this.entityManager = entityManager; - this.extractor = PersistenceProvider.fromEntityManager(entityManager); - } + private EntityManager entityManager; + private PersistenceProvider extractor; - @SuppressWarnings("unchecked") - @Override - @NonNull - protected JpaRepositoryImplementation getTargetRepository(RepositoryInformation information, @NonNull EntityManager entityManager) { - Class repositoryInterface = information.getRepositoryInterface(); + public BaseRepositoryFactory(EntityManager entityManager) { + super(entityManager); + this.entityManager = entityManager; + this.extractor = PersistenceProvider.fromEntityManager(entityManager); + } - if (isBaseRepository(repositoryInterface)) { - JpaEntityInformation entityInformation = getEntityInformation((Class) information.getDomainType()); + @SuppressWarnings("unchecked") + @Override + @NonNull + protected JpaRepositoryImplementation getTargetRepository( + RepositoryInformation information, @NonNull EntityManager entityManager) { + Class repositoryInterface = information.getRepositoryInterface(); - return new BaseRepositoryImpl<>(entityInformation, entityManager); - } - return super.getTargetRepository(information, entityManager); - } + if (isBaseRepository(repositoryInterface)) { + JpaEntityInformation entityInformation = + getEntityInformation((Class) information.getDomainType()); - @Override - @NonNull - protected Class getRepositoryBaseClass(RepositoryMetadata metadata) { - if (isBaseRepository(metadata.getRepositoryInterface())) { - return BaseRepositoryImpl.class; - } - return super.getRepositoryBaseClass(metadata); + return new BaseRepositoryImpl<>(entityInformation, entityManager); } - - private boolean isBaseRepository(Class repositoryInterface) { - return BaseRepository.class.isAssignableFrom(repositoryInterface); + return super.getTargetRepository(information, entityManager); + } + + @Override + @NonNull + protected Class getRepositoryBaseClass(RepositoryMetadata metadata) { + if (isBaseRepository(metadata.getRepositoryInterface())) { + return BaseRepositoryImpl.class; } + return super.getRepositoryBaseClass(metadata); + } + private boolean isBaseRepository(Class repositoryInterface) { + return BaseRepository.class.isAssignableFrom(repositoryInterface); + } } diff --git a/src/main/java/com/sondertara/joya/init/BaseRepositoryFactoryBean.java b/src/main/java/com/sondertara/joya/init/BaseRepositoryFactoryBean.java index 88e83ee..53ef367 100644 --- a/src/main/java/com/sondertara/joya/init/BaseRepositoryFactoryBean.java +++ b/src/main/java/com/sondertara/joya/init/BaseRepositoryFactoryBean.java @@ -1,5 +1,6 @@ package com.sondertara.joya.init; +import com.sondertara.joya.jpa.repository.BaseRepositoryImpl; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean; import org.springframework.data.repository.core.support.RepositoryFactorySupport; @@ -9,25 +10,25 @@ import java.io.Serializable; /** - * 简单实现 factory bean + * The factory bean to create {@link BaseRepositoryImpl} * * @author huangxiaohu */ -public class BaseRepositoryFactoryBean, T, ID extends Serializable> extends JpaRepositoryFactoryBean { +public class BaseRepositoryFactoryBean, T, ID extends Serializable> + extends JpaRepositoryFactoryBean { - /** - * Creates a new {@link JpaRepositoryFactoryBean} for the given repository interface. - * - * @param repositoryInterface must not be {@literal null}. - */ - public BaseRepositoryFactoryBean(Class repositoryInterface) { - super(repositoryInterface); - } - - @Override - @NonNull - protected RepositoryFactorySupport createRepositoryFactory(@NonNull EntityManager entityManager) { - return new BaseRepositoryFactory<>(entityManager); - } + /** + * Creates a new {@link JpaRepositoryFactoryBean} for the given repository interface. + * + * @param repositoryInterface must not be {@literal null}. + */ + public BaseRepositoryFactoryBean(Class repositoryInterface) { + super(repositoryInterface); + } + @Override + @NonNull + protected RepositoryFactorySupport createRepositoryFactory(@NonNull EntityManager entityManager) { + return new BaseRepositoryFactory<>(entityManager); + } } diff --git a/src/main/java/com/sondertara/joya/init/JoyaRepositoryFactoryBean.java b/src/main/java/com/sondertara/joya/init/JoyaRepositoryFactoryBean.java index d739ff8..8fe49eb 100644 --- a/src/main/java/com/sondertara/joya/init/JoyaRepositoryFactoryBean.java +++ b/src/main/java/com/sondertara/joya/init/JoyaRepositoryFactoryBean.java @@ -19,62 +19,67 @@ /** * JoyaRepository Factory - *

- * It will inject the joyaRepository and joyaSpringContext {@link JoyaSpringContext}which is a SpringContext util + * + *

It will inject the joyaRepository and joyaSpringContext {@link JoyaSpringContext}which is a + * SpringContext util * * @author huangxiaohu * @date 2021/11/15 12:09 * @since 1.0.1 */ -public class JoyaRepositoryFactoryBean extends AbstractFactoryBean implements ApplicationContextAware { - private static final String CONTEXT_HOLDER = "joyaSpringContext"; - private EntityManager entityManager; - private ConfigurableApplicationContext applicationContext; - - @PersistenceContext - public void setEntityManager(EntityManager entityManager) { - this.entityManager = entityManager; - } +public class JoyaRepositoryFactoryBean extends AbstractFactoryBean + implements ApplicationContextAware { + private static final String CONTEXT_HOLDER = "joyaSpringContext"; + private EntityManager entityManager; + private ConfigurableApplicationContext applicationContext; + @PersistenceContext + public void setEntityManager(EntityManager entityManager) { + this.entityManager = entityManager; + } - @Override - public Class getObjectType() { - return JoyaRepository.class; - } + @Override + public Class getObjectType() { + return JoyaRepository.class; + } - @Override - @NonNull - protected JoyaRepository createInstance() { - if (this.entityManager == null) { - throw new IllegalArgumentException("'entityManager' is required"); - } - registerJoyaSpringContext(); - logger.info("Initializing Joya Sql."); - return new JoyaRepository(entityManager); + @Override + @NonNull + protected JoyaRepository createInstance() { + if (this.entityManager == null) { + throw new IllegalArgumentException("'entityManager' is required"); } + registerJoyaSpringContext(); + logger.info("Initializing Joya Sql."); + return new JoyaRepository(entityManager); + } + @Override + public void setApplicationContext(@NonNull ApplicationContext applicationContext) + throws BeansException { + Assert.isTrue( + applicationContext instanceof ConfigurableApplicationContext, + "ApplicationContext does not implement ConfigurableApplicationContext"); + this.applicationContext = (ConfigurableApplicationContext) applicationContext; + } - @Override - public void setApplicationContext(@NonNull ApplicationContext applicationContext) throws BeansException { - Assert.isTrue(applicationContext instanceof ConfigurableApplicationContext, - "ApplicationContext does not implement ConfigurableApplicationContext"); - this.applicationContext = (ConfigurableApplicationContext) applicationContext; + public void registerJoyaSpringContext() { + if (applicationContext.containsBean(CONTEXT_HOLDER)) { + Object bean = applicationContext.getBean(CONTEXT_HOLDER); + if (bean.getClass().isAssignableFrom(JoyaSpringContext.class)) { + return; + } else { + throw new RuntimeException( + StringFormatter.format("The bean name of '{}' is duplicated", CONTEXT_HOLDER)); + } } + BeanDefinitionBuilder beanDefinitionBuilder = + BeanDefinitionBuilder.genericBeanDefinition(JoyaSpringContext.class); - public void registerJoyaSpringContext() { - if (applicationContext.containsBean(CONTEXT_HOLDER)) { - Object bean = applicationContext.getBean(CONTEXT_HOLDER); - if (bean.getClass().isAssignableFrom(JoyaSpringContext.class)) { - return; - } else { - throw new RuntimeException(StringFormatter.format("The bean name of '{}' is duplicated", CONTEXT_HOLDER)); - } - } - BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(JoyaSpringContext.class); - - BeanDefinition beanDefinition = beanDefinitionBuilder.getRawBeanDefinition(); - BeanDefinitionRegistry definitionRegistry = (BeanDefinitionRegistry) applicationContext.getBeanFactory(); - definitionRegistry.registerBeanDefinition(CONTEXT_HOLDER, beanDefinition); - applicationContext.getBean(CONTEXT_HOLDER, JoyaSpringContext.class); - } + BeanDefinition beanDefinition = beanDefinitionBuilder.getRawBeanDefinition(); + BeanDefinitionRegistry definitionRegistry = + (BeanDefinitionRegistry) applicationContext.getBeanFactory(); + definitionRegistry.registerBeanDefinition(CONTEXT_HOLDER, beanDefinition); + applicationContext.getBean(CONTEXT_HOLDER, JoyaSpringContext.class); + } } diff --git a/src/main/java/com/sondertara/joya/jpa/repository/BaseRepository.java b/src/main/java/com/sondertara/joya/jpa/repository/BaseRepository.java index e47587a..2f2f976 100644 --- a/src/main/java/com/sondertara/joya/jpa/repository/BaseRepository.java +++ b/src/main/java/com/sondertara/joya/jpa/repository/BaseRepository.java @@ -11,218 +11,209 @@ import java.util.Map; /** - *

抽象DAO层基类 提供一些简便方法
+ * 抽象DAO层基类 提供一些简便方法
* 泛型 : T 表示实体类型;ID表示主键类型 - *

+ * + *

* * @author huangxiaohu */ @NoRepositoryBean -public interface BaseRepository extends PagingAndSortingRepository/*, JpaSpecificationExecutor*/ { - - Class getEntityClass(); - - String getEntityName(); - - - /** - * find map from table rows - * - * @param nativeSql sql - * @param camelCase parse key to camelCase - * @return list - */ - Map findMapBySql(NativeSqlQuery nativeSql, boolean camelCase); - - /** - * find map list from table rows - * - * @param nativeSql sql - * @param camelCase parse key to camelCase - * @return list - */ - List> findMapListBySql(NativeSqlQuery nativeSql, boolean camelCase); - - /** - * find map list from table rows - * - * @param sql sql - * @param params query params - * @param camelCase parse key to camelCase - * @return list - */ - List> findMapListBySql(String sql, List params, boolean camelCase); - - /** - * find single row to map - * - * @param sql sql - * @param params params - * @param camelCase parse key to camelCase - * @return map - */ - Map findMapBySql(String sql, List params, boolean camelCase); - - - /** - * 使用SQL查询列表,数据已map形式封装 - * - * @param querySql hql - * @param params param - * @return the list of row map - */ - List> findMapListByHql(String querySql, final Map params); - - /** - * 使用SQL查询对象 - * - * @param querySql sql - * @param type - * @param clazz target class - * @param params query params - * @return object - */ - X findObjectBySql(String querySql, Class clazz, final Map params); - - /** - * 查询单个对象 - * - * @param hql hql - * @param params params - * @return Object - */ - X findObjectByHql(String hql, final Map params); - - /** - * sql query to Map - * - * @param querySql sql - * @param params param - * @return Map - */ - public Map findMapBySql(String querySql, final Map params); - - /** - * 执行SQL语句 - * - * @param sql sql - * @param params param - * @return the effect row count - */ - public int executeSql(String sql, final Map params); - - - /** - * 根据查询SQL,返回对象列表 - * - * @param querySql 查询语句 - * @param params 参数MAP格式 - * @return list - */ - List findListBySql(String querySql, Map params); - - - /** - * save - * - * @param s s - * @param s - * @return s - */ - @NonNull - S saveIgnoreNull(@NonNull S s); - - - /** - * batch delete - * - * @param ids id list - */ - void deleteById(Iterable ids); - - /** - * entity manger all flush - */ - void flush(); - - /** - * save and flush - * - * @param s entity - * @param entity - * @return entity - */ - S saveAndFlush(S s); - - - /** - * delete all - */ - void deleteAllInBatch(); - - - /** - * 查询map - * - * @return map - */ - Map mGetAll(); - - /** - * get as map - * - * @param ids id list - * @return map - */ - Map mGetAllById(Iterable ids); - - /** - * query by sql - * - * @param sql sql - * @param clazz target - * @param params params - * @return List - */ - List findListBySql(String sql, Class clazz, Object... params); - - /** - * 根据Hql查询列表 - * - * @param queryJql hql - * @param params param - * @return list - */ - X findListByHql(String queryJql, final Map params); - - /** - * query by native sql query - * - * @param nativeSql query - * @param resultClass result class - * @param target - * @return list - */ - List findListBySql(NativeSqlQuery nativeSql, Class resultClass); - - /** - * query page - * - * @param nativeSql native query - * @param resultClass result bean - * @param pageNo pageNo minimum is 0 - * @param pageSize pageSize - * @return Page - */ - Page queryPageBySql(NativeSqlQuery nativeSql, Class resultClass, Integer pageNo, Integer pageSize); - - /** - * count by hql - * - * @param hql hql - * @param params param - * @return count - */ - long countByHql(final String hql, final Object... params); - +public interface BaseRepository + extends PagingAndSortingRepository /*, JpaSpecificationExecutor*/ { + + Class getEntityClass(); + + String getEntityName(); + + /** + * find map from table rows + * + * @param nativeSql sql + * @param camelCase parse key to camelCase + * @return list + */ + Map findMapBySql(NativeSqlQuery nativeSql, boolean camelCase); + + /** + * find map list from table rows + * + * @param nativeSql sql + * @param camelCase parse key to camelCase + * @return list + */ + List> findMapListBySql(NativeSqlQuery nativeSql, boolean camelCase); + + /** + * find map list from table rows + * + * @param sql sql + * @param params query params + * @param camelCase parse key to camelCase + * @return list + */ + List> findMapListBySql(String sql, List params, boolean camelCase); + + /** + * find single row to map + * + * @param sql sql + * @param params params + * @param camelCase parse key to camelCase + * @return map + */ + Map findMapBySql(String sql, List params, boolean camelCase); + + /** + * 使用SQL查询列表,数据已map形式封装 + * + * @param querySql hql + * @param params param + * @return the list of row map + */ + List> findMapListByHql(String querySql, final Map params); + + /** + * 使用SQL查询对象 + * + * @param querySql sql + * @param type + * @param clazz target class + * @param params query params + * @return object + */ + X findObjectBySql(String querySql, Class clazz, final Map params); + + /** + * 查询单个对象 + * + * @param hql hql + * @param params params + * @return Object + */ + X findObjectByHql(String hql, final Map params); + + /** + * sql query to Map + * + * @param querySql sql + * @param params param + * @return Map + */ + public Map findMapBySql(String querySql, final Map params); + + /** + * 执行SQL语句 + * + * @param sql sql + * @param params param + * @return the effect row count + */ + public int executeSql(String sql, final Map params); + + /** + * 根据查询SQL,返回对象列表 + * + * @param querySql 查询语句 + * @param params 参数MAP格式 + * @return list + */ + List findListBySql(String querySql, Map params); + + /** + * save + * + * @param s s + * @param s + * @return s + */ + @NonNull + S saveIgnoreNull(@NonNull S s); + + /** + * batch delete + * + * @param ids id list + */ + void deleteById(Iterable ids); + + /** entity manger all flush */ + void flush(); + + /** + * save and flush + * + * @param s entity + * @param entity + * @return entity + */ + S saveAndFlush(S s); + + /** delete all */ + void deleteAllInBatch(); + + /** + * 查询map + * + * @return map + */ + Map mGetAll(); + + /** + * get as map + * + * @param ids id list + * @return map + */ + Map mGetAllById(Iterable ids); + + /** + * query by sql + * + * @param sql sql + * @param clazz target + * @param params params + * @return List + */ + List findListBySql(String sql, Class clazz, Object... params); + + /** + * 根据Hql查询列表 + * + * @param queryJql hql + * @param params param + * @return list + */ + X findListByHql(String queryJql, final Map params); + + /** + * query by native sql query + * + * @param nativeSql query + * @param resultClass result class + * @param target + * @return list + */ + List findListBySql(NativeSqlQuery nativeSql, Class resultClass); + + /** + * query page + * + * @param nativeSql native query + * @param resultClass result bean + * @param pageNo pageNo minimum is 0 + * @param pageSize pageSize + * @return Page + */ + Page queryPageBySql( + NativeSqlQuery nativeSql, Class resultClass, Integer pageNo, Integer pageSize); + + /** + * count by hql + * + * @param hql hql + * @param params param + * @return count + */ + long countByHql(final String hql, final Object... params); } diff --git a/src/main/java/com/sondertara/joya/jpa/repository/BaseRepositoryImpl.java b/src/main/java/com/sondertara/joya/jpa/repository/BaseRepositoryImpl.java index 752e627..6aa6a78 100644 --- a/src/main/java/com/sondertara/joya/jpa/repository/BaseRepositoryImpl.java +++ b/src/main/java/com/sondertara/joya/jpa/repository/BaseRepositoryImpl.java @@ -1,14 +1,12 @@ package com.sondertara.joya.jpa.repository; - import com.sondertara.joya.core.query.NativeSqlQuery; import com.sondertara.joya.hibernate.transformer.AliasToBeanTransformer; import com.sondertara.joya.hibernate.transformer.AliasToMapResultTransformer; import com.sondertara.joya.utils.BeanUtil; import com.sondertara.joya.utils.SqlUtils; import org.apache.commons.beanutils.BeanUtils; -import org.hibernate.Session; -import org.hibernate.query.internal.NativeQueryImpl; +import org.hibernate.query.NativeQuery; import org.hibernate.transform.Transformers; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; @@ -36,378 +34,363 @@ * @author huangxiaohu */ @Transactional(readOnly = true) -public class BaseRepositoryImpl extends SimpleJpaRepository implements BaseRepository { - - private final JpaEntityInformation eif; - private final EntityManager em; - private final Class entityClass; - private final String entityName; - private final String idName; - - public BaseRepositoryImpl(JpaEntityInformation eif, EntityManager em) { - super(eif, em); - this.eif = eif; - this.em = em; - - this.entityClass = eif.getJavaType(); - this.entityName = eif.getEntityName(); - this.idName = eif.getIdAttributeNames().iterator().next(); - } - - - @Override - public Class getEntityClass() { - return this.entityClass; - } - - @Override - public String getEntityName() { - return entityName; - } - - - @Override - @NonNull - @SuppressWarnings("unchecked") - @Transactional(rollbackFor = Exception.class) - public S saveIgnoreNull(@NonNull S entity) { - if (this.eif.isNew(entity)) { - this.em.persist(entity); - return entity; - } else { - T po = super.findById(((ID) Objects.requireNonNull(eif.getId(entity)))).orElse(null); - if (Objects.nonNull(po)) { - BeanUtil.copyPropertiesIgnoreNull(entity, po); - return (S) this.em.merge(po); - } - return this.em.merge(entity); - } - } - - - /** - * 根据主键删除相应实体 - */ - @Override - @Transactional(rollbackFor = Exception.class, readOnly = false) - public void deleteById(Iterable ids) { - if (ObjectUtils.isEmpty(ids)) { - return; - } - List models = new ArrayList<>(); - for (ID id : ids) { - T model; - try { - model = entityClass.getDeclaredConstructor().newInstance(); - } catch (Exception e) { - throw new RuntimeException("batch delete " + entityClass + " error", e); - } - try { - BeanUtils.setProperty(model, idName, id); - } catch (Exception e) { - throw new RuntimeException("batch delete " + entityClass + " error, can not set id", e); - } - models.add(model); - } - deleteAllInBatch(models); - - } - - - /** - * 查询,并封装到Map - */ - @Override - public Map mGetAll() { - return toMap(findAll()); - } - - @Override - public Map mGetAllById(Iterable ids) { - return toMap(findAllById(ids)); - } - - @SuppressWarnings("unchecked") - private Map toMap(List list) { - Map result = new LinkedHashMap<>(); - for (T t : list) { - if (t != null) { - result.put((ID) eif.getId(t), t); - } - } - return result; - } - - - @Override - @SuppressWarnings("unchecked") - public List findListBySql(String sql, Class clazz, Object... params) { - Query query = em.unwrap(Session.class).createNativeQuery(sql); - setParameters(query, params); - return query.unwrap(NativeQueryImpl.class).setResultTransformer(new AliasToBeanTransformer<>(clazz)).list(); - } - - @Override - @SuppressWarnings("unchecked") - public List findListBySql(NativeSqlQuery nativeSql, Class resultClass) { - Query query = em.unwrap(Session.class).createNativeQuery(nativeSql.toSql()); - setParameters(query, nativeSql.getParams()); - return query.unwrap(NativeQueryImpl.class).setResultTransformer(new AliasToBeanTransformer<>(resultClass)).list(); - } - - @Override - @SuppressWarnings("unchecked") - public Page queryPageBySql(NativeSqlQuery nativeSql, Class resultClass, Integer pageNo, Integer pageSize) { - String sqlStr = nativeSql.toSql(); - - //获取总记录数 - Session session = em.unwrap(Session.class); - String countSql = SqlUtils.buildCountSql(sqlStr); - Query countQuery = session.createNativeQuery(countSql); - setParameters(countQuery, nativeSql.getParams()); - - long totalRecord = ((Number) countQuery.getSingleResult()).longValue(); - - //获取分页结果 - Query pageQuery = session.createNativeQuery(sqlStr); - setParameters(pageQuery, nativeSql.getParams()); - - List result = totalRecord == 0 ? new ArrayList<>(0) : pageQuery.setFirstResult(pageNo).setMaxResults(pageSize).unwrap(NativeQueryImpl.class).setResultTransformer(new AliasToBeanTransformer<>(resultClass)).list(); - - return new PageImpl<>(result, PageRequest.of(pageNo, pageSize), totalRecord); - } - - - /** - * 根据ql和按照索引顺序的params查询一个实体 - */ - public T findOneByHql(final String ql, final Object... params) { - List list = findAllByHql(ql, PageRequest.of(0, 1), params); - if (list.size() > 0) { - return list.get(0); - } - return null; - } - - public List findAllByHql(final String ql, final Object... params) { - return findAllByHql(ql, (Pageable) null, params); - } - - /** - * 根据ql和按照索引顺序的params执行ql,sort存储排序信息 null表示不排序 - * - * @param ql hql sql - * @param sort null表示不排序 - * @param params List orders = this.find("SELECT o FROM Order o WHERE o.storeId = ? and o.code = ? order by o.createTime desc", storeId, code); - * @return list - */ - @SuppressWarnings("unchecked") - public List findAllByHqL(final String ql, final Sort sort, final Object... params) { - Query query = em.createQuery(ql + prepareOrder(sort)); - setParameters(query, params); - return query.getResultList(); - } - - /** - * 根据ql和按照索引顺序的params执行ql,pageable存储分页信息 null表示不分页 - * - * @param ql hql - * @param pageable null表示不分页 - * @param params param - * @return list - */ - @SuppressWarnings("unchecked") - public List findAllByHql(final String ql, final Pageable pageable, final Object... params) { - Query query = em.createQuery(ql + prepareOrder(pageable != null ? pageable.getSort() : null)); - setParameters(query, params); - if (pageable != null) { - query.setFirstResult((int) pageable.getOffset()); - query.setMaxResults(pageable.getPageSize()); - } - return query.getResultList(); - } - - /** - * 根据ql和按照索引顺序的params执行ql统计 - */ - @Override - public long countByHql(final String ql, final Object... params) { - Query query = em.createQuery(ql); - setParameters(query, params); - return (Long) query.getSingleResult(); - } - - - /** - * 拼排序 - */ - private String prepareOrder(Sort sort) { - return (sort == null || !sort.iterator().hasNext()) ? "" : (" order by " + sort.toString().replace(":", " ")); - } - - /** - * 按顺序设置Query参数 - */ - private void setParameters(Query query, Object[] params) { - if (params != null) { - for (int i = 0; i < params.length; i++) { - query.setParameter(i + 1, params[i]); - } - } - } - - /** - * 按顺序设置Query参数 - */ - private void setParameters(Query query, List params) { - if (params != null) { - for (int i = 0; i < params.size(); i++) { - query.setParameter(i + 1, params.get(i)); - } - } - } +public class BaseRepositoryImpl extends SimpleJpaRepository + implements BaseRepository { + + private final JpaEntityInformation eif; + private final EntityManager em; + private final Class entityClass; + private final String entityName; + private final String idName; + + public BaseRepositoryImpl(JpaEntityInformation eif, EntityManager em) { + super(eif, em); + this.eif = eif; + this.em = em; + + this.entityClass = eif.getJavaType(); + this.entityName = eif.getEntityName(); + this.idName = eif.getIdAttributeNames().iterator().next(); + } + + @Override + public Class getEntityClass() { + return this.entityClass; + } + + @Override + public String getEntityName() { + return entityName; + } + + @Override + @NonNull + @SuppressWarnings("unchecked") + @Transactional(rollbackFor = Exception.class) + public S saveIgnoreNull(@NonNull S entity) { + if (this.eif.isNew(entity)) { + this.em.persist(entity); + return entity; + } else { + T po = super.findById(((ID) Objects.requireNonNull(eif.getId(entity)))).orElse(null); + if (Objects.nonNull(po)) { + BeanUtil.copyPropertiesIgnoreNull(entity, po); + return (S) this.em.merge(po); + } + return this.em.merge(entity); + } + } + + /** 根据主键删除相应实体 */ + @Override + @Transactional(rollbackFor = Exception.class, readOnly = false) + public void deleteById(Iterable ids) { + if (ObjectUtils.isEmpty(ids)) { + return; + } + List models = new ArrayList<>(); + for (ID id : ids) { + T model; + try { + model = entityClass.getDeclaredConstructor().newInstance(); + } catch (Exception e) { + throw new RuntimeException("batch delete " + entityClass + " error", e); + } + try { + BeanUtils.setProperty(model, idName, id); + } catch (Exception e) { + throw new RuntimeException("batch delete " + entityClass + " error, can not set id", e); + } + models.add(model); + } + deleteAllInBatch(models); + } + + /** 查询,并封装到Map */ + @Override + public Map mGetAll() { + return toMap(findAll()); + } + + @Override + public Map mGetAllById(Iterable ids) { + return toMap(findAllById(ids)); + } + + @SuppressWarnings("unchecked") + private Map toMap(List list) { + Map result = new LinkedHashMap<>(); + for (T t : list) { + if (t != null) { + result.put((ID) eif.getId(t), t); + } + } + return result; + } + + @Override + @SuppressWarnings({"unchecked", "deprecation"}) + public List findListBySql(String sql, Class clazz, Object... params) { + Query query = em.createNativeQuery(sql); + setParameters(query, params); + return query + .unwrap(NativeQuery.class) + .setResultTransformer(new AliasToBeanTransformer<>(clazz)) + .list(); + } + + @Override + public List findListBySql(NativeSqlQuery nativeSql, Class resultClass) { + return findListBySql( + nativeSql.toSql(), + resultClass, + null != nativeSql.getParams() ? nativeSql.getParams().toArray() : new Object[0]); + } + + @Override + @SuppressWarnings({"unchecked", "deprecation"}) + public Page queryPageBySql( + NativeSqlQuery nativeSql, Class resultClass, Integer pageNo, Integer pageSize) { + String sqlStr = nativeSql.toSql(); + + // 获取总记录数 + String countSql = SqlUtils.buildCountSql(sqlStr); + Query countQuery = em.createNativeQuery(countSql); + setParameters(countQuery, nativeSql.getParams()); + + long totalRecord = ((Number) countQuery.getSingleResult()).longValue(); + + // 获取分页结果 + Query pageQuery = em.createNativeQuery(sqlStr); + setParameters(pageQuery, nativeSql.getParams()); + List result = + totalRecord == 0 + ? new ArrayList<>(0) + : pageQuery + .setFirstResult(pageNo) + .setMaxResults(pageSize) + .unwrap(NativeQuery.class) + .setResultTransformer(new AliasToBeanTransformer<>(resultClass)) + .list(); + + return new PageImpl<>(result, PageRequest.of(pageNo, pageSize), totalRecord); + } + + /** 根据ql和按照索引顺序的params查询一个实体 */ + public T findOneByHql(final String ql, final Object... params) { + List list = findAllByHql(ql, PageRequest.of(0, 1), params); + if (list.size() > 0) { + return list.get(0); + } + return null; + } + + public List findAllByHql(final String ql, final Object... params) { + return findAllByHql(ql, null, params); + } + + /** + * 根据ql和按照索引顺序的params执行ql,sort存储排序信息 null表示不排序 + * + * @param ql hql sql + * @param sort null表示不排序 + * @param params List orders = this.find("SELECT o FROM Order o WHERE o.storeId = ? and + * o.code = ? order by o.createTime desc", storeId, code); + * @return list + */ + @SuppressWarnings("unchecked") + public List findAllByHqL(final String ql, final Sort sort, final Object... params) { + Query query = em.createQuery(ql + prepareOrder(sort)); + setParameters(query, params); + return query.getResultList(); + } + + /** + * 根据ql和按照索引顺序的params执行ql,pageable存储分页信息 null表示不分页 + * + * @param ql hql + * @param pageable null表示不分页 + * @param params param + * @return list + */ + @SuppressWarnings("unchecked") + public List findAllByHql(final String ql, final Pageable pageable, final Object... params) { + Query query = em.createQuery(ql + prepareOrder(pageable != null ? pageable.getSort() : null)); + setParameters(query, params); + if (pageable != null) { + query.setFirstResult((int) pageable.getOffset()); + query.setMaxResults(pageable.getPageSize()); + } + return query.getResultList(); + } + + /** 根据ql和按照索引顺序的params执行ql统计 */ + @Override + public long countByHql(final String ql, final Object... params) { + Query query = em.createQuery(ql); + setParameters(query, params); + return (Long) query.getSingleResult(); + } + + /** 拼排序 */ + private String prepareOrder(Sort sort) { + return (sort == null || !sort.iterator().hasNext()) + ? "" + : (" order by " + sort.toString().replace(":", " ")); + } + + /** 按顺序设置Query参数 */ + private void setParameters(Query query, Object[] params) { + if (params != null && params.length > 0) { + for (int i = 0; i < params.length; i++) { + query.setParameter(i + 1, params[i]); + } + } + } + + /** 按顺序设置Query参数 */ + private void setParameters(Query query, List params) { + if (params != null && params.size() > 0) { + for (int i = 0; i < params.size(); i++) { + query.setParameter(i + 1, params.get(i)); + } + } + } + + @SuppressWarnings("unchecked") + @Override + public X findObjectByHql(String queryJql, Map params) { + + Query query = this.createQueryWithNameParam(queryJql, params); + + return (X) query.getSingleResult(); + } + + @SuppressWarnings("unchecked") + @Override + public X findListByHql(String queryJql, Map params) { + + Query query = this.createQueryWithNameParam(queryJql, params); + + return (X) query.getResultList(); + } + + @Override + public List> findMapListBySql(NativeSqlQuery nativeSql, boolean camelCase) { + return findMapListBySql(nativeSql.toSql(), nativeSql.getParams(), camelCase); + } + + @Override + public Map findMapBySql(NativeSqlQuery nativeSql, boolean camelCase) { + return findMapBySql(nativeSql.toSql(), nativeSql.getParams(), camelCase); + } + + /** (non-Javadoc) */ + @Override + @SuppressWarnings({"unchecked", "deprecation"}) + public List> findMapListBySql( + String querySql, List params, boolean camelCase) { + Query query = em.createNativeQuery(querySql); + setParameters(query, params); + query + .unwrap(NativeQuery.class) + .setResultTransformer(AliasToMapResultTransformer.getInstance(camelCase)); + return query.getResultList(); + } + + @Override + @SuppressWarnings({"unchecked", "deprecation"}) + public Map findMapBySql(String querySql, List params, boolean camelCase) { + Query query = em.createNativeQuery(querySql); + setParameters(query, params); + query + .unwrap(NativeQuery.class) + .setResultTransformer(AliasToMapResultTransformer.getInstance(camelCase)); + return (Map) query.getSingleResult(); + } + + @SuppressWarnings({"unchecked", "deprecation"}) + @Override + public List> findMapListByHql(String querySql, Map params) { + Query query = this.createSqlQueryWithNameParam(querySql, params); + query.unwrap(NativeQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP); + return query.getResultList(); + } + + @Override + @SuppressWarnings({"unchecked"}) + public List findListBySql(String querySql, Map params) { + Query query = this.createSqlQueryWithNameParam(querySql, params); + return query.getResultList(); + } + + /** + * 根据查询JQL语句与命名参数列表创建Query对象,JQL中参数按名称绑定 + * + * @param values 参数Map + */ + @SuppressWarnings({"unchecked"}) + public Query createQueryWithNameParam(final String queryJql, final Map values) { + + Query query = this.em.createQuery(queryJql); + + if (values != null) { + + for (Map.Entry stringEntry : values.entrySet()) { + + Map.Entry entry = (Map.Entry) stringEntry; + query.setParameter(entry.getKey(), entry.getValue()); + } + } + return query; + } - @SuppressWarnings("unchecked") - @Override - public X findObjectByHql(String queryJql, Map params) { + /** + * 根据查询SQL语句与命名参数列表创建Query对象,SQL中参数按名称绑定 + * + * @param values 参数Map + */ + @SuppressWarnings({"unchecked"}) + public Query createSqlQueryWithNameParam(final String querySql, final Map values) { - Query query = this.createQueryWithNameParam(queryJql, params); + Query query = this.em.createNativeQuery(querySql); - return (X) query.getSingleResult(); - } - - - @SuppressWarnings("unchecked") - @Override - public X findListByHql(String queryJql, Map params) { - - Query query = this.createQueryWithNameParam(queryJql, params); - - return (X) query.getResultList(); - } - - - @Override - public List> findMapListBySql(NativeSqlQuery nativeSql, boolean camelCase) { - - return findMapListBySql(nativeSql, camelCase); - } - - @Override - public Map findMapBySql(NativeSqlQuery nativeSql, boolean camelCase) { - - return findMapBySql(nativeSql, camelCase); - } - - /** - * (non-Javadoc) - */ - @Override - @SuppressWarnings({"unchecked"}) - public List> findMapListBySql(String querySql, List params, boolean camelCase) { - Query query = em.createNativeQuery(querySql); - setParameters(query, params); - query.unwrap(NativeQueryImpl.class).setResultTransformer(AliasToMapResultTransformer.getInstance(camelCase)); - return query.getResultList(); - } - - @Override - @SuppressWarnings({"unchecked"}) - public Map findMapBySql(String querySql, List params, boolean camelCase) { - Query query = em.createNativeQuery(querySql); - setParameters(query, params); - query.unwrap(NativeQueryImpl.class).setResultTransformer(AliasToMapResultTransformer.getInstance(camelCase)); - return (Map) query.getSingleResult(); - } - - @SuppressWarnings({"unchecked"}) - @Override - public List> findMapListByHql(String querySql, Map params) { - Query query = this.createSqlQueryWithNameParam(querySql, params); - query.unwrap(NativeQueryImpl.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP); - return query.getResultList(); - } - - @SuppressWarnings("unchecked") - @Override - public List findListBySql(String querySql, Map params) { - Query query = this.createSqlQueryWithNameParam(querySql, params); - return query.getResultList(); - } - - /** - * 根据查询JQL语句与命名参数列表创建Query对象,JQL中参数按名称绑定 - * - * @param values 参数Map - */ - @SuppressWarnings({"rawtypes", "unchecked"}) - public Query createQueryWithNameParam(final String queryJql, final Map values) { - - Query query = this.em.createQuery(queryJql); - - if (values != null) { - - for (Map.Entry stringEntry : values.entrySet()) { - - Map.Entry entry = (Map.Entry) stringEntry; - query.setParameter(entry.getKey(), entry.getValue()); - } - - } - - return query; - } - - /** - * 根据查询SQL语句与命名参数列表创建Query对象,SQL中参数按名称绑定 - * - * @param values 参数Map - */ - @SuppressWarnings({"unchecked"}) - public Query createSqlQueryWithNameParam(final String querySql, final Map values) { - - Query query = this.em.createNativeQuery(querySql); - - if (values != null) { - - for (Map.Entry stringEntry : values.entrySet()) { - - Map.Entry entry = (Map.Entry) stringEntry; - query.setParameter(entry.getKey(), entry.getValue()); - } - - } - - return query; - } - - - @Override - public X findObjectBySql(String querySql, Class clazz, final Map params) { - Query query = this.createSqlQueryWithNameParam(querySql, params); - - Object result = query.getSingleResult(); - - return com.sondertara.common.util.BeanUtils.beanToBean(result, clazz); - } - - @SuppressWarnings({"unchecked"}) - @Override - public Map findMapBySql(String querySql, Map params) { - - Query query = this.createSqlQueryWithNameParam(querySql, params); - - query.unwrap(NativeQueryImpl.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP); - return (Map) query.getSingleResult(); - } - - - @Override - public int executeSql(String sql, Map params) { - - Query query = this.createSqlQueryWithNameParam(sql, params); - return query.executeUpdate(); - } + if (values != null) { + + for (Map.Entry stringEntry : values.entrySet()) { + Map.Entry entry = (Map.Entry) stringEntry; + query.setParameter(entry.getKey(), entry.getValue()); + } + } + + return query; + } + + @Override + public X findObjectBySql(String querySql, Class clazz, final Map params) { + Query query = this.createSqlQueryWithNameParam(querySql, params); + + Object result = query.getSingleResult(); + + return com.sondertara.common.util.BeanUtils.beanToBean(result, clazz); + } + + @SuppressWarnings({"unchecked", "deprecation"}) + @Override + public Map findMapBySql(String querySql, Map params) { + + Query query = this.createSqlQueryWithNameParam(querySql, params); + + query.unwrap(NativeQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP); + return (Map) query.getSingleResult(); + } + + @Override + public int executeSql(String sql, Map params) { + + Query query = this.createSqlQueryWithNameParam(sql, params); + return query.executeUpdate(); + } } diff --git a/src/main/java/com/sondertara/joya/jpa/repository/JoyaRepository.java b/src/main/java/com/sondertara/joya/jpa/repository/JoyaRepository.java index 1817307..5bb97d6 100644 --- a/src/main/java/com/sondertara/joya/jpa/repository/JoyaRepository.java +++ b/src/main/java/com/sondertara/joya/jpa/repository/JoyaRepository.java @@ -1,6 +1,5 @@ package com.sondertara.joya.jpa.repository; - import com.sondertara.common.util.CollectionUtils; import com.sondertara.common.util.StringFormatter; import com.sondertara.joya.cache.TableClassCache; @@ -47,371 +46,400 @@ @Transactional(readOnly = true) public class JoyaRepository { - private static final Logger log = LoggerFactory.getLogger(JoyaRepository.class); - private static final String SQL_VIEW_SWITCH = "joya.sql-view"; - - private static final int BATCH_SIZE = 500; - - private final EntityManager em; - - public JoyaRepository(EntityManager em) { - this.em = em; + private static final Logger log = LoggerFactory.getLogger(JoyaRepository.class); + private static final String SQL_VIEW_SWITCH = "joya.sql-view"; + + private static final int BATCH_SIZE = 500; + + private final EntityManager em; + + public JoyaRepository(EntityManager em) { + this.em = em; + } + + /** + * 查询list + * + * @param sql 原生sql + * @param resultClass 目标实体 + * @param params 参数 + * @param 泛型 + * @return list + */ + @SuppressWarnings({"unchecked", "deprecation"}) + public List findListBySql(String sql, Class resultClass, Object... params) { + if (JoyaSpringContext.getConfig(SQL_VIEW_SWITCH, true)) { + log.info("[findListBySql] SQL:\nJoya-SQL: {}", sql); } - - - /** - * 查询list - * - * @param sql 原生sql - * @param resultClass 目标实体 - * @param params 参数 - * @param 泛型 - * @return list - */ - @SuppressWarnings({"unchecked"}) - public List findListBySql(String sql, Class resultClass, Object... params) { - if (JoyaSpringContext.getConfig(SQL_VIEW_SWITCH, true)) { - log.info("[findListBySql] SQL:\nJoya-SQL: {}", sql); - } - Query query = em.createNativeQuery(sql); - setParameters(query, params); - return query.unwrap(NativeQuery.class).setResultTransformer(new AliasToBeanTransformer<>(resultClass)).list(); + Query query = em.createNativeQuery(sql); + setParameters(query, params); + return query + .unwrap(NativeQuery.class) + .setResultTransformer(new AliasToBeanTransformer<>(resultClass)) + .list(); + } + + /** + * find to list + * + * @param nativeSql native query + * @param resultClass result class + * @param generic + * @return list + */ + @SuppressWarnings({"unchecked", "deprecation"}) + public List findListBySql(NativeSqlQuery nativeSql, Class resultClass) { + + if (JoyaSpringContext.getConfig(SQL_VIEW_SWITCH, true)) { + log.info("[findListBySql] SQL:\nJoya-SQL: {}", nativeSql.toSql()); } - - /** - * find to list - * - * @param nativeSql native query - * @param resultClass result class - * @param generic - * @return list - */ - @SuppressWarnings("unchecked") - public List findListBySql(NativeSqlQuery nativeSql, Class resultClass) { - - if (JoyaSpringContext.getConfig(SQL_VIEW_SWITCH, true)) { - log.info("[findListBySql] SQL:\nJoya-SQL: {}", nativeSql.toSql()); - } - Query query = em.createNativeQuery(nativeSql.toSql()); - setParameters(query, nativeSql.getParams()); - return query.unwrap(NativeQuery.class).setResultTransformer(new AliasToBeanTransformer<>(resultClass)).list(); + Query query = em.createNativeQuery(nativeSql.toSql()); + setParameters(query, nativeSql.getParams()); + return query + .unwrap(NativeQuery.class) + .setResultTransformer(new AliasToBeanTransformer<>(resultClass)) + .list(); + } + + /** + * find map list from table rows + * + * @param nativeSql sql + * @param params params + * @param camelCase parse key to camelCase + * @return list + */ + public List> findMapListBySql( + NativeSqlQuery nativeSql, List params, boolean camelCase) { + + return findMapListBySql(nativeSql.toSql(), params, camelCase); + } + + /** + * find map from table rows + * + * @param nativeSql sql + * @param params params + * @param camelCase parse key to camelCase + * @return list + */ + public Map findMapBySql( + NativeSqlQuery nativeSql, List params, boolean camelCase) { + + return findMapBySql(nativeSql.toSql(), params, camelCase); + } + + /** (non-Javadoc) */ + @SuppressWarnings({"unchecked", "deprecation"}) + public List> findMapListBySql( + String querySql, List params, boolean camelCase) { + Query query = em.createNativeQuery(querySql); + setParameters(query, params); + query + .unwrap(NativeQuery.class) + .setResultTransformer(AliasToMapResultTransformer.getInstance(camelCase)); + return query.getResultList(); + } + + @SuppressWarnings({"unchecked", "deprecation"}) + public Map findMapBySql(String querySql, List params, boolean camelCase) { + Query query = em.createNativeQuery(querySql); + setParameters(query, params); + query + .unwrap(NativeQuery.class) + .setResultTransformer(AliasToMapResultTransformer.getInstance(camelCase)); + return (Map) query.getSingleResult(); + } + + /** + * query page + * + * @param resultClass the result class + * @param queryParam query params + * @param targetClass the target query table + * @param the type of result + * @return pagination result + */ + public PageResult queryPage( + PageQueryParam queryParam, Class resultClass, Class... targetClass) { + NativeSqlQuery nativeSqlQuery = JoyaPageConvert.buildNativeQuery(queryParam, targetClass); + return queryPage(nativeSqlQuery, resultClass, queryParam.getPage(), queryParam.getPageSize()); + } + + /** + * query page + * + * @param resultClass the result class + * @param queryParam query params + * @param joinPart the join table + * @param the type of result + * @return pagination result + */ + public PageResult queryPage( + PageQueryParam queryParam, Class resultClass, UnaryOperator joinPart) { + + NativeSqlQuery nativeSqlQuery = JoyaPageConvert.buildNativeQuery(queryParam, joinPart); + return queryPage(nativeSqlQuery, resultClass, queryParam.getPage(), queryParam.getPageSize()); + } + + /** + * query page + * + * @param sql sql query + * @param resultClass result class + * @param pageNo page start + * @param pageSize page size + * @param the type of result + * @param params the query params + * @return pagination result + */ + @SuppressWarnings({"unchecked", "deprecation"}) + public PageResult queryPage( + String sql, Class resultClass, Integer pageNo, Integer pageSize, Object... params) { + Boolean opened = JoyaSpringContext.getConfig(SQL_VIEW_SWITCH, false); + if (opened) { + log.info("[queryPage] SQL:\nJoya-SQL: {}", sql); } - - /** - * find map list from table rows - * - * @param nativeSql sql - * @param params params - * @param camelCase parse key to camelCase - * @return list - */ - public List> findMapListBySql(NativeSqlQuery nativeSql, List params, boolean camelCase) { - - return findMapListBySql(nativeSql.toSql(), params, camelCase); + // get the count sql + String countSql = SqlUtils.buildCountSql(sql); + Query countQuery = em.createNativeQuery(countSql); + setParameters(countQuery, params); + long totalRecord = ((Number) countQuery.getSingleResult()).longValue(); + + // the query + Query pageQuery = em.createNativeQuery(sql); + + setParameters(pageQuery, params); + + List result = + totalRecord == 0 + ? new ArrayList<>(0) + : pageQuery + .setFirstResult(pageNo * pageSize) + .setMaxResults(pageSize) + .unwrap(NativeQuery.class) + .setResultTransformer(new AliasToBeanTransformer<>(resultClass)) + .list(); + return new PageResult<>(pageNo, pageSize, totalRecord, result); + } + + /** + * query page + * + * @param nativeSql sql query + * @param resultClass result class + * @param pageNo page start + * @param pageSize page size + * @param the type of result + * @return pagination result + */ + @SuppressWarnings({"unchecked", "deprecation"}) + public PageResult queryPage( + NativeSqlQuery nativeSql, Class resultClass, Integer pageNo, Integer pageSize) { + return queryPage( + nativeSql.toSql(), + resultClass, + pageNo, + pageSize, + null == nativeSql.getParams() ? new Object[0] : nativeSql.getParams().toArray()); + } + + /** 根据ql和按照索引顺序的params查询一个实体 */ + public T findOneByHql(final String hql, final Object... params) { + List list = findAllByHql(hql, PageRequest.of(0, 1), params); + if (list.size() > 0) { + return list.get(0); } - - /** - * find map from table rows - * - * @param nativeSql sql - * @param params params - * @param camelCase parse key to camelCase - * @return list - */ - public Map findMapBySql(NativeSqlQuery nativeSql, List params, boolean camelCase) { - - return findMapBySql(nativeSql.toSql(), params, camelCase); + return null; + } + + public List findAllByHql(final String hql, final Object... params) { + return findAllByHql(hql, (Pageable) null, params); + } + + /** + * 根据ql和按照索引顺序的params执行ql,sort存储排序信息 null表示不排序 + * + * @param ql hql sql + * @param sort null表示不排序 + * @param params List orders = this.find("SELECT o FROM Order o WHERE o.storeId = ? and + * o.code = ? order by o.createTime desc", storeId, code); + * @return list + */ + @SuppressWarnings("unchecked") + public List findAllByHql(final String ql, final Sort sort, final Object... params) { + Query query = em.createQuery(ql + prepareOrder(sort)); + setParameters(query, params); + return query.getResultList(); + } + + /** + * 根据ql和按照索引顺序的params执行ql,pageable存储分页信息 null表示不分页 + * + * @param ql hql + * @param pageable null表示不分页 + * @param params query + * @return list + */ + @SuppressWarnings("unchecked") + public List findAllByHql( + final String ql, final Pageable pageable, final Object... params) { + Query query = em.createQuery(ql + prepareOrder(pageable != null ? pageable.getSort() : null)); + setParameters(query, params); + if (pageable != null) { + query.setFirstResult((int) pageable.getOffset()); + query.setMaxResults(pageable.getPageSize()); } - - /** - * (non-Javadoc) - */ - @SuppressWarnings({"unchecked"}) - public List> findMapListBySql(String querySql, List params, boolean camelCase) { - Query query = em.createNativeQuery(querySql); - setParameters(query, params); - query.unwrap(NativeQuery.class).setResultTransformer(AliasToMapResultTransformer.getInstance(camelCase)); - return query.getResultList(); + return query.getResultList(); + } + + /** 根据ql和按照索引顺序的params执行ql统计 */ + public long countByHql(final String ql, final Object... params) { + Query query = em.createQuery(ql); + setParameters(query, params); + return (Long) query.getSingleResult(); + } + + /** 拼排序 */ + private String prepareOrder(Sort sort) { + return (sort == null || !sort.iterator().hasNext()) + ? "" + : (" order by " + sort.toString().replace(":", " ")); + } + + /** 按顺序设置Query参数 */ + private void setParameters(Query query, Object[] params) { + if (params != null && params.length > 0) { + for (int i = 0; i < params.length; i++) { + query.setParameter(i + 1, params[i]); + } } - - @SuppressWarnings({"unchecked"}) - public Map findMapBySql(String querySql, List params, boolean camelCase) { - Query query = em.createNativeQuery(querySql); - setParameters(query, params); - query.unwrap(NativeQuery.class).setResultTransformer(AliasToMapResultTransformer.getInstance(camelCase)); - return (Map) query.getSingleResult(); + } + + /** 按顺序设置Query参数 */ + private void setParameters(Query query, List params) { + if (params != null) { + for (int i = 0; i < params.size(); i++) { + query.setParameter(i + 1, params.get(i)); + } } - - /** - * query page - * - * @param resultClass the result class - * @param queryParam query params - * @param targetClass the target query table - * @param the type of result - * @return pagination result - */ - public PageResult queryPage(PageQueryParam queryParam, Class resultClass, Class... targetClass) { - NativeSqlQuery nativeSqlQuery = JoyaPageConvert.buildNativeQuery(queryParam, targetClass); - return queryPage(nativeSqlQuery, resultClass, queryParam.getPage(), queryParam.getPageSize()); - - } - - /** - * query page - * - * @param resultClass the result class - * @param queryParam query params - * @param joinPart the join table - * @param the type of result - * @return pagination result - */ - public PageResult queryPage(PageQueryParam queryParam, Class resultClass, UnaryOperator joinPart) { - - NativeSqlQuery nativeSqlQuery = JoyaPageConvert.buildNativeQuery(queryParam, joinPart); - return queryPage(nativeSqlQuery, resultClass, queryParam.getPage(), queryParam.getPageSize()); - - } - - - /** - * query page - * - * @param sql sql query - * @param resultClass result class - * @param pageNo page start - * @param pageSize page size - * @param the type of result - * @param params the query params - * @return pagination result - */ - @SuppressWarnings("unchecked") - public PageResult queryPage(String sql, Class resultClass, Integer pageNo, Integer pageSize, Object... params) { - Boolean opened = JoyaSpringContext.getConfig(SQL_VIEW_SWITCH, false); - if (opened) { - log.info("[queryPage] SQL:\nJoya-SQL: {}", sql); + } + + /** + * Batch update, first execute the update operation, then the insert operation, it is not + * performed in the transaction by default, and support Spring transaction management + * 批量更新,先执行更新操作,后执行插入操作,默认不是在事务中执行,支持Spring事务管理 + * + *

The pojo need extends {@link PersistEntity},and explicitly specifies whether it is new by + * the field isNew 实体需要继承{@link PersistEntity} 通过isNew字段来表示是否是新建还是更新,默认是新增 + * + *

1.对于mysql主键自增这种实体通过重写{@link PersistEntity#isNew()}判断主键是否为null就可以标识是否新增 + * 2.对于通过序列来设置主键值的情形,在构造dataList时,需要显示调用{@link PersistEntity#setNew(boolean)} 来标识是否新增 + * + * @param dataList 数据 + * @param 类型 + */ + @Transactional(readOnly = false, propagation = Propagation.SUPPORTS) + public void batchUpdate(List dataList) throws SQLException { + try { + if (CollectionUtils.isEmpty(dataList)) { + return; + } + List insertList = new ArrayList<>(); + List updateList = new ArrayList<>(); + for (T data : dataList) { + TableEntity table = TableClassCache.getInstance().getTable(data, true); + if (data.isNew() || table.getData().get(table.getPrimaryKey()) == null) { + if (table.getData().get(table.getPrimaryKey()) == null) { + table.getData().remove(table.getPrimaryKey()); + } + insertList.add(table); + } else { + updateList.add(table); } - // get the count sql - String countSql = SqlUtils.buildCountSql(sql); - Query countQuery = em.createNativeQuery(countSql); - setParameters(countQuery, params); - long totalRecord = ((Number) countQuery.getSingleResult()).longValue(); - - // the query - Query pageQuery = em.createNativeQuery(sql); - - setParameters(pageQuery, params); - - - List result = totalRecord == 0 ? new ArrayList<>(0) : pageQuery.setFirstResult(pageNo * pageSize).setMaxResults(pageSize).unwrap(NativeQuery.class).setResultTransformer(new AliasToBeanTransformer<>(resultClass)).list(); - - return new PageResult<>(pageNo, pageSize, totalRecord, result); - } - - /** - * query page - * - * @param nativeSql sql query - * @param resultClass result class - * @param pageNo page start - * @param pageSize page size - * @param the type of result - * @return pagination result - */ - @SuppressWarnings("unchecked") - public PageResult queryPage(NativeSqlQuery nativeSql, Class resultClass, Integer pageNo, Integer pageSize) { - return queryPage(nativeSql.toSql(), resultClass, pageNo, pageSize, null == nativeSql.getParams() ? new Object[0] : nativeSql.getParams().toArray()); - } - - - /** - * 根据ql和按照索引顺序的params查询一个实体 - */ - public T findOneByHql(final String hql, final Object... params) { - List list = findAllByHql(hql, PageRequest.of(0, 1), params); - if (list.size() > 0) { - return list.get(0); + } + String insertSql = null; + if (insertList.size() > 0) { + TableEntity table = insertList.get(0); + Map data = table.getData(); + // auto increment + if (null == data.get(table.getPrimaryKey())) { + data.remove(table.getPrimaryKey()); } - return null; - } - - public List findAllByHql(final String hql, final Object... params) { - return findAllByHql(hql, (Pageable) null, params); - } - - /** - * 根据ql和按照索引顺序的params执行ql,sort存储排序信息 null表示不排序 - * - * @param ql hql sql - * @param sort null表示不排序 - * @param params List orders = this.find("SELECT o FROM Order o WHERE o.storeId = ? and o.code = ? order by o.createTime desc", storeId, code); - * @return list - */ - @SuppressWarnings("unchecked") - public List findAllByHql(final String ql, final Sort sort, final Object... params) { - Query query = em.createQuery(ql + prepareOrder(sort)); - setParameters(query, params); - return query.getResultList(); - } - - /** - * 根据ql和按照索引顺序的params执行ql,pageable存储分页信息 null表示不分页 - * - * @param ql hql - * @param pageable null表示不分页 - * @param params query - * @return list - */ - @SuppressWarnings("unchecked") - public List findAllByHql(final String ql, final Pageable pageable, final Object... params) { - Query query = em.createQuery(ql + prepareOrder(pageable != null ? pageable.getSort() : null)); - setParameters(query, params); - if (pageable != null) { - query.setFirstResult((int) pageable.getOffset()); - query.setMaxResults(pageable.getPageSize()); + List set = data.keySet().stream().map(s -> "?").collect(Collectors.toList()); + insertSql = + StringFormatter.format( + "insert into {}({}) values({})", + table.getTableName(), + String.join(",", data.keySet()), + String.join(",", set)); + } + String updateSql = null; + if (updateList.size() > 0) { + TableEntity table = updateList.get(0); + StringJoiner sj = new StringJoiner(", "); + Map map = table.getData(); + Object primaryKeyValue = map.remove(table.getPrimaryKey()); + for (String key : map.keySet()) { + sj.add(key + " = ?"); } - return query.getResultList(); - } - - /** - * 根据ql和按照索引顺序的params执行ql统计 - */ - public long countByHql(final String ql, final Object... params) { - Query query = em.createQuery(ql); - setParameters(query, params); - return (Long) query.getSingleResult(); + map.put(table.getPrimaryKey(), primaryKeyValue); + updateSql = + StringFormatter.format( + "update {} set {} where {} = ?", + table.getTableName(), + sj.toString(), + table.getPrimaryKey()); + } + try (Session session = em.unwrap(Session.class)) { + String finalUpdateSql = updateSql; + String finalInsertSql = insertSql; + log.info( + "Batch update start,insert size is:{},update size is:{}", + insertList.size(), + updateList.size()); + session.doWork( + connection -> { + if (null != finalUpdateSql) { + batchUpdate(finalUpdateSql, updateList, connection); + } + if (null != finalInsertSql) { + batchUpdate(finalInsertSql, insertList, connection); + } + }); + } + } catch (Exception e) { + throw new SQLException(e.getMessage(), e.getCause()); } + log.info("Batch update completed."); + } - /** - * 拼排序 - */ - private String prepareOrder(Sort sort) { - return (sort == null || !sort.iterator().hasNext()) ? "" : (" order by " + sort.toString().replace(":", " ")); + private void batchUpdate(String sql, List rows, Connection connection) + throws SQLException { + if (null == sql) { + return; } - - /** - * 按顺序设置Query参数 - */ - private void setParameters(Query query, Object[] params) { - if (params != null && params.length > 0) { - for (int i = 0; i < params.length; i++) { - query.setParameter(i + 1, params[i]); - } - } - } - - /** - * 按顺序设置Query参数 - */ - private void setParameters(Query query, List params) { - if (params != null) { - for (int i = 0; i < params.size(); i++) { - query.setParameter(i + 1, params.get(i)); - } + SimpleBatchPreparedStatementSetter setter = new SimpleBatchPreparedStatementSetter(rows); + PreparedStatement ps = connection.prepareStatement(sql); + int batchSize = setter.getBatchSize(); + if (JdbcUtils.supportsBatchUpdates(ps.getConnection())) { + for (int j = 0; j < batchSize; j++) { + setter.setValues(ps, j); + ps.addBatch(); + if ((j + 1) % BATCH_SIZE == 0 || j == batchSize - 1) { + ps.executeBatch(); + ps.clearBatch(); } + } + } else { + for (int i = 0; i < batchSize; i++) { + setter.setValues(ps, i); + ps.executeUpdate(); + } } - - /** - * Batch update, first execute the update operation, then the insert operation, - * it is not performed in the transaction by default, and support Spring transaction management - * 批量更新,先执行更新操作,后执行插入操作,默认不是在事务中执行,支持Spring事务管理 - *

- * The pojo need extends {@link PersistEntity},and explicitly specifies whether it is new by the field isNew - * 实体需要继承{@link PersistEntity} 通过isNew字段来表示是否是新建还是更新,默认是新增 - *

- * 1.对于mysql主键自增这种实体通过重写{@link PersistEntity#isNew()}判断主键是否为null就可以标识是否新增 - * 2.对于通过序列来设置主键值的情形,在构造dataList时,需要显示调用{@link PersistEntity#setNew(boolean)} 来标识是否新增 - * - * @param dataList 数据 - * @param 类型 - */ - @Transactional(readOnly = false, propagation = Propagation.SUPPORTS) - public void batchUpdate(List dataList) throws SQLException { - try { - if (CollectionUtils.isEmpty(dataList)) { - return; - } - List insertList = new ArrayList<>(); - List updateList = new ArrayList<>(); - for (T data : dataList) { - TableEntity table = TableClassCache.getInstance().getTable(data, true); - if (data.isNew() || table.getData().get(table.getPrimaryKey()) == null) { - if (table.getData().get(table.getPrimaryKey()) == null) { - table.getData().remove(table.getPrimaryKey()); - } - insertList.add(table); - } else { - updateList.add(table); - } - } - String insertSql = null; - if (insertList.size() > 0) { - TableEntity table = insertList.get(0); - Map data = table.getData(); - // auto increment - if (null == data.get(table.getPrimaryKey())) { - data.remove(table.getPrimaryKey()); - } - List set = data.keySet().stream().map(s -> "?").collect(Collectors.toList()); - insertSql = StringFormatter.format("insert into {}({}) values({})", table.getTableName(), String.join(",", data.keySet()), String.join(",", set)); - } - String updateSql = null; - if (updateList.size() > 0) { - TableEntity table = updateList.get(0); - StringJoiner sj = new StringJoiner(", "); - Map map = table.getData(); - Object primaryKeyValue = map.remove(table.getPrimaryKey()); - for (String key : map.keySet()) { - sj.add(key + " = ?"); - } - map.put(table.getPrimaryKey(), primaryKeyValue); - updateSql = StringFormatter.format("update {} set {} where {} = ?", table.getTableName(), sj.toString(), table.getPrimaryKey()); - } - try (Session session = em.unwrap(Session.class)) { - String finalUpdateSql = updateSql; - String finalInsertSql = insertSql; - log.info("Batch update start,insert size is:{},update size is:{}", insertList.size(), updateList.size()); - session.doWork(connection -> { - if (null != finalUpdateSql) { - batchUpdate(finalUpdateSql, updateList, connection); - } - if (null != finalInsertSql) { - batchUpdate(finalInsertSql, insertList, connection); - } - }); - } - } catch (Exception e) { - throw new SQLException(e.getMessage(), e.getCause()); - } - - log.info("Batch update completed."); - } - - private void batchUpdate(String sql, List rows, Connection connection) throws SQLException { - if (null == sql) { - return; - } - SimpleBatchPreparedStatementSetter setter = new SimpleBatchPreparedStatementSetter(rows); - PreparedStatement ps = connection.prepareStatement(sql); - int batchSize = setter.getBatchSize(); - if (JdbcUtils.supportsBatchUpdates(ps.getConnection())) { - for (int j = 0; j < batchSize; j++) { - setter.setValues(ps, j); - ps.addBatch(); - if ((j + 1) % BATCH_SIZE == 0 || j == batchSize - 1) { - ps.executeBatch(); - ps.clearBatch(); - } - } - } else { - for (int i = 0; i < batchSize; i++) { - setter.setValues(ps, i); - ps.executeUpdate(); - } - } - if (!ps.isClosed()) { - ps.close(); - } + if (!ps.isClosed()) { + ps.close(); } + } } diff --git a/src/main/java/com/sondertara/joya/jpa/repository/statment/SimpleBatchPreparedStatementSetter.java b/src/main/java/com/sondertara/joya/jpa/repository/statment/SimpleBatchPreparedStatementSetter.java index ade3960..61038a0 100644 --- a/src/main/java/com/sondertara/joya/jpa/repository/statment/SimpleBatchPreparedStatementSetter.java +++ b/src/main/java/com/sondertara/joya/jpa/repository/statment/SimpleBatchPreparedStatementSetter.java @@ -17,31 +17,30 @@ */ public class SimpleBatchPreparedStatementSetter implements BatchPreparedStatementSetter { - - private final List rows; - - public SimpleBatchPreparedStatementSetter(List rows) { - this.rows = rows; + private final List rows; + + public SimpleBatchPreparedStatementSetter(List rows) { + this.rows = rows; + } + + @Override + public void setValues(@NonNull PreparedStatement ps, int i) throws SQLException { + TableEntity table = rows.get(i); + Map data = table.getData(); + int colIndex = 0; + for (Object value : data.values()) { + colIndex++; + if (value instanceof SqlParameterValue) { + SqlParameterValue paramValue = (SqlParameterValue) value; + StatementCreatorUtils.setParameterValue(ps, colIndex, paramValue, paramValue.getValue()); + } else { + StatementCreatorUtils.setParameterValue(ps, colIndex, SqlTypeValue.TYPE_UNKNOWN, value); + } } + } - @Override - public void setValues(@NonNull PreparedStatement ps, int i) throws SQLException { - TableEntity table = rows.get(i); - Map data = table.getData(); - int colIndex = 0; - for (Object value : data.values()) { - colIndex++; - if (value instanceof SqlParameterValue) { - SqlParameterValue paramValue = (SqlParameterValue) value; - StatementCreatorUtils.setParameterValue(ps, colIndex, paramValue, paramValue.getValue()); - } else { - StatementCreatorUtils.setParameterValue(ps, colIndex, SqlTypeValue.TYPE_UNKNOWN, value); - } - } - } - - @Override - public int getBatchSize() { - return this.rows.size(); - } + @Override + public int getBatchSize() { + return this.rows.size(); + } } diff --git a/src/main/java/com/sondertara/joya/utils/BeanUtil.java b/src/main/java/com/sondertara/joya/utils/BeanUtil.java index 12657fc..6d62f0f 100644 --- a/src/main/java/com/sondertara/joya/utils/BeanUtil.java +++ b/src/main/java/com/sondertara/joya/utils/BeanUtil.java @@ -15,106 +15,97 @@ import java.util.Map; /** - * Bean属性拷贝 - * Bean深度转换 - * Bean深度转换 + * Bean属性拷贝 Bean深度转换 Bean深度转换 * * @author huangxiaohu */ public abstract class BeanUtil extends org.springframework.beans.BeanUtils { - /** - * 修改spring的BeanUtils,不用null覆盖已有的值 - */ - public static void copyPropertiesIgnoreNull(Object source, Object target) throws BeansException { - Assert.notNull(source, "Source must not be null"); - Assert.notNull(target, "Target must not be null"); - Class clazz = target.getClass(); - PropertyDescriptor[] targetProps = getPropertyDescriptors(clazz); - for (PropertyDescriptor targetProp : targetProps) { - if (targetProp.getWriteMethod() != null) { - PropertyDescriptor sourceProp = getPropertyDescriptor(source.getClass(), targetProp.getName()); - if (sourceProp != null && sourceProp.getReadMethod() != null) { - try { - Method readMethod = sourceProp.getReadMethod(); - if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) { - readMethod.setAccessible(true); - } - Object value = readMethod.invoke(source); - // 这里判断以下value是否为空 当然这里也能进行一些特殊要求的处理 例如绑定时格式转换等等 - if (value != null) { - Method writeMethod = targetProp.getWriteMethod(); - if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) { - writeMethod.setAccessible(true); - } - writeMethod.invoke(target, value); - } - } catch (Throwable ex) { - throw new FatalBeanException("Could not copy properties from source to target", ex); - } - } + /** 修改spring的BeanUtils,不用null覆盖已有的值 */ + public static void copyPropertiesIgnoreNull(Object source, Object target) throws BeansException { + Assert.notNull(source, "Source must not be null"); + Assert.notNull(target, "Target must not be null"); + Class clazz = target.getClass(); + PropertyDescriptor[] targetProps = getPropertyDescriptors(clazz); + for (PropertyDescriptor targetProp : targetProps) { + if (targetProp.getWriteMethod() != null) { + PropertyDescriptor sourceProp = + getPropertyDescriptor(source.getClass(), targetProp.getName()); + if (sourceProp != null && sourceProp.getReadMethod() != null) { + try { + Method readMethod = sourceProp.getReadMethod(); + if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) { + readMethod.setAccessible(true); } + Object value = readMethod.invoke(source); + // 这里判断以下value是否为空 当然这里也能进行一些特殊要求的处理 例如绑定时格式转换等等 + if (value != null) { + Method writeMethod = targetProp.getWriteMethod(); + if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) { + writeMethod.setAccessible(true); + } + writeMethod.invoke(target, value); + } + } catch (Throwable ex) { + throw new FatalBeanException("Could not copy properties from source to target", ex); + } } + } } + } + /** Bean to Map */ + public static Map beanToMap(T bean) { + Map map = new HashMap<>(16); + if (bean != null) { + BeanMap beanMap = BeanMap.create(bean); - /** - * Bean to Map - */ - public static Map beanToMap(T bean) { - Map map = new HashMap<>(16); - if (bean != null) { - BeanMap beanMap = BeanMap.create(bean); - - for (Object key : beanMap.keySet()) { - if (beanMap.get(key) != null) { - map.put(key.toString(), beanMap.get(key)); - } - } + for (Object key : beanMap.keySet()) { + if (beanMap.get(key) != null) { + map.put(key.toString(), beanMap.get(key)); } - return map; + } } + return map; + } - /** - * Map --> Bean - */ - @SuppressWarnings({"unchecked", "rawtypes"}) - public static T mapToBean(Map map, T t) { - BeanMap beanMap = BeanMap.create(t); - beanMap.putAll(map); - return (T) beanMap.getBean(); - } + /** Map --> Bean */ + @SuppressWarnings({"unchecked", "rawtypes"}) + public static T mapToBean(Map map, T t) { + BeanMap beanMap = BeanMap.create(t); + beanMap.putAll(map); + return (T) beanMap.getBean(); + } - public static List> beansToMaps(List beanList) { - List> maps = new ArrayList<>(); - if (beanList == null || beanList.size() == 0) { - return null; - } - for (T bean : beanList) { - if (bean != null) { - Map beanToMaps = beanToMap(bean); - maps.add(beanToMaps); - } - } - return maps; + public static List> beansToMaps(List beanList) { + List> maps = new ArrayList<>(); + if (beanList == null || beanList.size() == 0) { + return null; } - - public static List mapsToBeans(List> mapList, Class t) { - List beans = new ArrayList<>(); - if (CollectionUtils.isEmpty(mapList)) { - return null; - } - for (Map map : mapList) { - T t1 = null; - try { - t1 = t.getDeclaredConstructor().newInstance(); - } catch (Exception e) { - e.printStackTrace(); - } - T t2 = mapToBean(map, t1); - beans.add(t2); - } - return beans; + for (T bean : beanList) { + if (bean != null) { + Map beanToMaps = beanToMap(bean); + maps.add(beanToMaps); + } } + return maps; + } + public static List mapsToBeans(List> mapList, Class t) { + List beans = new ArrayList<>(); + if (CollectionUtils.isEmpty(mapList)) { + return null; + } + for (Map map : mapList) { + T t1 = null; + try { + t1 = t.getDeclaredConstructor().newInstance(); + } catch (Exception e) { + e.printStackTrace(); + } + T t2 = mapToBean(map, t1); + beans.add(t2); + } + return beans; + } } diff --git a/src/main/java/com/sondertara/joya/utils/ClassUtils.java b/src/main/java/com/sondertara/joya/utils/ClassUtils.java deleted file mode 100644 index 3fa7e35..0000000 --- a/src/main/java/com/sondertara/joya/utils/ClassUtils.java +++ /dev/null @@ -1,202 +0,0 @@ -package com.sondertara.joya.utils; - -import com.sondertara.common.exception.TaraException; -import com.sondertara.common.util.StringUtils; -import com.sondertara.joya.core.model.TableEntity; - -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Id; -import javax.persistence.Table; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * @author skydu - */ -public class ClassUtils { - - /** - * @return get current classloader - */ - public static ClassLoader getDefaultClassLoader() { - ClassLoader cl = null; - try { - cl = Thread.currentThread().getContextClassLoader(); - } catch (Throwable ex) { - // Cannot access thread context ClassLoader - falling back... - } - if (cl == null) { - // No thread context class loader -> use class loader of this class. - cl = ClassUtils.class.getClassLoader(); - if (cl == null) { - // getClassLoader() returning null indicates the bootstrap ClassLoader - try { - cl = ClassLoader.getSystemClassLoader(); - } catch (Throwable ex) { - // Cannot access system ClassLoader - oh well, maybe the caller can live with - // null... - } - } - } - return cl; - } - - /** - * 获取类的所有字段(包括父类的) - * - * @param clazz class - * @return field - */ - public static List getFieldList(Class clazz) { - List fields = new ArrayList<>(); - Set filedNames = new HashSet<>(); - for (Class c = clazz; c != Object.class; c = c.getSuperclass()) { - try { - Field[] list = c.getDeclaredFields(); - for (Field field : list) { - String name = field.getName(); - if (filedNames.contains(name)) { - continue; - } - filedNames.add(field.getName()); - fields.add(field); - } - } catch (Exception e) { - throw new TaraException(e); - } - } - return fields; - } - - /** - * 获取一个实体类对应数据库字段 - * - * @param bean java pojo - * @param the class type of bean - * @return the table data - */ - public static TableEntity getTable(T bean, boolean readData) { - Map filedNames = new LinkedHashMap<>(); - Map relation = new HashMap<>(); - Class clazz = bean.getClass(); - Table table = clazz.getAnnotation(Table.class); - String tableName = null; - if (null != table) { - tableName = table.name(); - } else { - Entity entity = clazz.getAnnotation(Entity.class); - if (null != entity) { - tableName = entity.name(); - } - } - if (null == tableName) { - throw new TaraException("No [@Table] or [@Entity] annotation found for class->" + clazz); - } - - TableEntity tableDTO = new TableEntity(); - tableDTO.setTableName(tableName); - for (Class c = clazz; c != Object.class; c = c.getSuperclass()) { - try { - Field[] list = c.getDeclaredFields(); - for (Field field : list) { - if (Modifier.isStatic(field.getModifiers())) { - continue; - } - field.setAccessible(true); - String name = field.getName(); - name = StringUtils.toUnderlineCase(name); - Column column = field.getAnnotation(Column.class); - if (null != column) { - name = column.name(); - } - Id id = field.getAnnotation(Id.class); - if (null != id) { - tableDTO.setPrimaryKey(name); - tableDTO.setPrimaryKeyType(field.getType()); - } - if (filedNames.containsKey(name)) { - continue; - } - if (readData) { - filedNames.put(name, field.get(bean)); - } - relation.put(name, field.getName()); - } - } catch (Exception e) { - throw new TaraException(e); - } - } - - tableDTO.setData(filedNames); - tableDTO.setRelation(relation); - return tableDTO; - } - - - /** - * @param clazz - * @return the super class - */ - public static Class getSuperClassGenricType(Class clazz) { - Type genType = clazz.getGenericSuperclass(); - if (!(genType instanceof ParameterizedType)) { - if (genType instanceof Class) { - return getSuperClassGenricType((Class) genType); - } - return Object.class; - } - Type[] params = ((ParameterizedType) genType).getActualTypeArguments(); - if (params.length == 0) { - return Object.class; - } - return (Class) params[0]; - } - - - /** - * @param clazz the class - * @param fieldName field name - * @return the current Field - */ - public static Field getField(Class clazz, String fieldName) { - List fields = getFieldList(clazz); - for (Field field : fields) { - if (field.getName().equals(fieldName)) { - return field; - } - } - return null; - } - - - public static Field getExistedField(Class clazz, String fieldName) { - List fields = getFieldList(clazz); - for (Field field : fields) { - if (field.getName().equals(fieldName)) { - return field; - } - } - throw new TaraException("No such field " + fieldName + "/" + clazz.getSimpleName()); - } - - public static Class classForName(String name) throws ClassNotFoundException { - try { - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - if (classLoader != null) { - return classLoader.loadClass(name); - } - } catch (Throwable ignore) { - } - return Class.forName(name); - } -} diff --git a/src/main/java/com/sondertara/joya/utils/RestTemplateUtils.java b/src/main/java/com/sondertara/joya/utils/RestTemplateUtils.java index 2e35144..5432e33 100644 --- a/src/main/java/com/sondertara/joya/utils/RestTemplateUtils.java +++ b/src/main/java/com/sondertara/joya/utils/RestTemplateUtils.java @@ -1,6 +1,5 @@ package com.sondertara.joya.utils; - import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.sondertara.common.model.ResultDTO; @@ -31,541 +30,736 @@ import java.util.Map; import java.util.Objects; - /** * 自定义RestTemplate工具 * * @author huangxiaohu * @date 2021-06-20 */ - @Slf4j public class RestTemplateUtils { - /** - * 使用fastjson解析 - */ - private static volatile RestTemplate restTemplate; - - /** - * 连接超时,单位秒 - */ - private static final int CONNECT_TIMEOUT = 10; - /** - * 获取响应超时,单位秒 - */ - private static final int READ_TIMEOUT = 60; - - private static final String DISABLE_PRINT_CACHE_KEY = "RESTFUL_PRINT_RSP_CACHE"; - - public static RestTemplate getInstance() { - if (null == restTemplate) { - synchronized (RestTemplate.class) { - if (null == restTemplate) { -// FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter(); -// List supportedMediaTypes = new ArrayList<>(); -// supportedMediaTypes.add(MediaType.APPLICATION_JSON); -// supportedMediaTypes.add(MediaType.APPLICATION_ATOM_XML); -// supportedMediaTypes.add(MediaType.APPLICATION_FORM_URLENCODED); -// supportedMediaTypes.add(MediaType.APPLICATION_OCTET_STREAM); -// supportedMediaTypes.add(MediaType.APPLICATION_PDF); -// supportedMediaTypes.add(MediaType.APPLICATION_RSS_XML); -// supportedMediaTypes.add(MediaType.APPLICATION_XHTML_XML); -// supportedMediaTypes.add(MediaType.APPLICATION_XML); -// supportedMediaTypes.add(MediaType.IMAGE_GIF); -// supportedMediaTypes.add(MediaType.IMAGE_JPEG); -// supportedMediaTypes.add(MediaType.IMAGE_PNG); -// supportedMediaTypes.add(MediaType.TEXT_EVENT_STREAM); -// supportedMediaTypes.add(MediaType.TEXT_HTML); -// supportedMediaTypes.add(MediaType.TEXT_MARKDOWN); -// supportedMediaTypes.add(MediaType.TEXT_PLAIN); -// supportedMediaTypes.add(MediaType.TEXT_XML); -// -// fastJsonHttpMessageConverter.setSupportedMediaTypes(supportedMediaTypes); -// fastJsonHttpMessageConverter.setDefaultCharset(StandardCharsets.UTF_8); -// FastJsonConfig fastJsonConfig = new FastJsonConfig(); -// fastJsonConfig.setSerializerFeatures( -// SerializerFeature.WriteMapNullValue, -// SerializerFeature.WriteNullStringAsEmpty, -// SerializerFeature.WriteNullListAsEmpty, -// SerializerFeature.DisableCircularReferenceDetect); -// fastJsonHttpMessageConverter.setFastJsonConfig(fastJsonConfig); - restTemplate = new RestTemplateBuilder().setConnectTimeout(Duration.ofSeconds(CONNECT_TIMEOUT)).setReadTimeout(Duration.ofSeconds(READ_TIMEOUT)).build(); - - List> messageConverters = restTemplate.getMessageConverters(); - - for (int i = 0; i < messageConverters.size(); i++) { - HttpMessageConverter converter = messageConverters.get(i); - if (converter instanceof StringHttpMessageConverter) { - converter = new StringHttpMessageConverter(StandardCharsets.UTF_8); - messageConverters.set(i, converter); - break; - } - //} else if (converter instanceof MappingJackson2HttpMessageConverter) { - // List mediaTypes = new ArrayList<>(converter.getSupportedMediaTypes()); - // mediaTypes.add(MediaType.APPLICATION_OCTET_STREAM); - // MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = (MappingJackson2HttpMessageConverter) converter; - // - // mappingJackson2HttpMessageConverter.setSupportedMediaTypes(mediaTypes); - // messageConverters.set(i, mappingJackson2HttpMessageConverter); - //} - -// } else if (converter instanceof GsonHttpMessageConverter || converter instanceof MappingJackson2HttpMessageConverter) { -// converter = fastJsonHttpMessageConverter; -// messageConverters.set(i, converter); -// } - - } - - } - } - } - return restTemplate; - } - - private RestTemplateUtils() { - - } - - - /** - * Get 请求,参数放在url中 - * - * @param url url - * @param params 参数 - * @param responseType 接收响应的类 - * @return 响应结果 - */ - public static ResultDTO get(String url, Map params, Class responseType) { - return get(url, params, responseType, null); - } - - public static ResultDTO get(String url, Map params, ParameterizedTypeReference responseType) { - return get(url, params, responseType, null); - } - - /** - * post - * - * @param url url - * @param params 参数 - * @param responseType 接收响应的类 - * @return 响应结果 - */ - public static ResultDTO post(String url, Map params, Class responseType) { - return post(url, params, responseType, null); - } - - public static ResultDTO post(String url, Map params, ParameterizedTypeReference responseType) { - return post(url, params, responseType, null); - } - - /** - * Get 请求,参数放在url中 - * - * @param url url - * @param params 参数 - * @param headers 请求头 - * @param responseType 接收响应的类 - * @return 响应结果 - */ - @SuppressWarnings("unchecked") - public static ResultDTO get(String url, Map params, Class responseType, Map headers) { - log.info("RESTful get请求开始 url=[{}],params=[{}],responseType=[{}]", url, params, responseType); - long start = System.currentTimeMillis(); - try { - url = buildUrl(url, params); - HttpEntity> httpEntity = buildHttpEntity(params, buildHeaders(headers)); - ResponseEntity responseEntity = RestTemplateUtils.getInstance().exchange(url, HttpMethod.GET, httpEntity, responseType); - T result = responseEntity.getBody(); - if (Boolean.TRUE.equals(ThreadLocalUtil.get(DISABLE_PRINT_CACHE_KEY))) { - log.info("RESTful get请求结束 url=[{}],cost time=[{}],params=[{}]", url, System.currentTimeMillis() - start, params); - } else { - log.info("RESTful get请求结束 url=[{}],cost time=[{}],params=[{}],responseType=[{}],result=[{}]", url, System.currentTimeMillis() - start, params, responseType, result); - } - return ResultDTO.success(result); - } catch (Exception e) { - log.error("RESTful get请求失败 url=[{}],params=[{}],responseType=[{}],errMsg:{}", url, params, responseType, e.getMessage()); - return handleFailResult(e); - } finally { - ThreadLocalUtil.clear(); - } - } + /** 使用fastjson解析 */ + private static volatile RestTemplate restTemplate; + /** 连接超时,单位秒 */ + private static final int CONNECT_TIMEOUT = 10; + /** 获取响应超时,单位秒 */ + private static final int READ_TIMEOUT = 60; - public static ResultDTO get(String url, Map params, ParameterizedTypeReference responseType, Map headers) { - log.info("RESTful get请求开始 url=[{}],params=[{}],responseType=[{}]", url, params, responseType); - long start = System.currentTimeMillis(); - try { - url = buildUrl(url, params); - HttpEntity> httpEntity = buildHttpEntity(params, buildHeaders(headers)); - ResponseEntity responseEntity = RestTemplateUtils.getInstance().exchange(url, HttpMethod.GET, httpEntity, responseType); + private static final String DISABLE_PRINT_CACHE_KEY = "RESTFUL_PRINT_RSP_CACHE"; - T result = responseEntity.getBody(); - if (Boolean.TRUE.equals(ThreadLocalUtil.get(DISABLE_PRINT_CACHE_KEY))) { - log.info("RESTful get请求结束 url=[{}],cost time=[{}],params=[{}]", url, System.currentTimeMillis() - start, params); - } else { - log.info("RESTful get请求结束 url=[{}],cost time=[{}],params=[{}],responseType=[{}],result=[{}]", url, System.currentTimeMillis() - start, params, responseType, result); + public static RestTemplate getInstance() { + if (null == restTemplate) { + synchronized (RestTemplate.class) { + if (null == restTemplate) { + // FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new + // FastJsonHttpMessageConverter(); + // List supportedMediaTypes = new ArrayList<>(); + // supportedMediaTypes.add(MediaType.APPLICATION_JSON); + // supportedMediaTypes.add(MediaType.APPLICATION_ATOM_XML); + // supportedMediaTypes.add(MediaType.APPLICATION_FORM_URLENCODED); + // supportedMediaTypes.add(MediaType.APPLICATION_OCTET_STREAM); + // supportedMediaTypes.add(MediaType.APPLICATION_PDF); + // supportedMediaTypes.add(MediaType.APPLICATION_RSS_XML); + // supportedMediaTypes.add(MediaType.APPLICATION_XHTML_XML); + // supportedMediaTypes.add(MediaType.APPLICATION_XML); + // supportedMediaTypes.add(MediaType.IMAGE_GIF); + // supportedMediaTypes.add(MediaType.IMAGE_JPEG); + // supportedMediaTypes.add(MediaType.IMAGE_PNG); + // supportedMediaTypes.add(MediaType.TEXT_EVENT_STREAM); + // supportedMediaTypes.add(MediaType.TEXT_HTML); + // supportedMediaTypes.add(MediaType.TEXT_MARKDOWN); + // supportedMediaTypes.add(MediaType.TEXT_PLAIN); + // supportedMediaTypes.add(MediaType.TEXT_XML); + // + // + // fastJsonHttpMessageConverter.setSupportedMediaTypes(supportedMediaTypes); + // + // fastJsonHttpMessageConverter.setDefaultCharset(StandardCharsets.UTF_8); + // FastJsonConfig fastJsonConfig = new FastJsonConfig(); + // fastJsonConfig.setSerializerFeatures( + // SerializerFeature.WriteMapNullValue, + // SerializerFeature.WriteNullStringAsEmpty, + // SerializerFeature.WriteNullListAsEmpty, + // SerializerFeature.DisableCircularReferenceDetect); + // fastJsonHttpMessageConverter.setFastJsonConfig(fastJsonConfig); + restTemplate = + new RestTemplateBuilder() + .setConnectTimeout(Duration.ofSeconds(CONNECT_TIMEOUT)) + .setReadTimeout(Duration.ofSeconds(READ_TIMEOUT)) + .build(); + + List> messageConverters = restTemplate.getMessageConverters(); + + for (int i = 0; i < messageConverters.size(); i++) { + HttpMessageConverter converter = messageConverters.get(i); + if (converter instanceof StringHttpMessageConverter) { + converter = new StringHttpMessageConverter(StandardCharsets.UTF_8); + messageConverters.set(i, converter); + break; } - return ResultDTO.success(result); - } catch (Exception e) { - log.error("RESTful get请求失败 url=[{}],params=[{}],responseType=[{}],errMsg:{}", url, params, responseType, e.getMessage()); - return handleFailResult(e); - } finally { - ThreadLocalUtil.clear(); + // } else if (converter instanceof MappingJackson2HttpMessageConverter) { + // List mediaTypes = new ArrayList<>(converter.getSupportedMediaTypes()); + // mediaTypes.add(MediaType.APPLICATION_OCTET_STREAM); + // MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = + // (MappingJackson2HttpMessageConverter) converter; + // + // mappingJackson2HttpMessageConverter.setSupportedMediaTypes(mediaTypes); + // messageConverters.set(i, mappingJackson2HttpMessageConverter); + // } + + // } else if (converter instanceof GsonHttpMessageConverter || + // converter instanceof MappingJackson2HttpMessageConverter) { + // converter = fastJsonHttpMessageConverter; + // messageConverters.set(i, converter); + // } + + } } + } } - - /** - * POST 请求 参数放在body中 兼容form和json - * - * @param url url - * @param params 请求参数 - * @param headers 请求头 - * @param responseType 响应映射类 - * @return 请求结果 - */ - public static ResultDTO post(String url, Map params, Class responseType, Map headers) { - log.info("RESTful post请求开始 url=[{}],params=[{}],responseType=[{}]", url, JSON.toJSONString(params), responseType); - long start = System.currentTimeMillis(); - try { - HttpEntity> httpEntity = buildHttpEntity(params, buildHeaders(headers)); - - T result = RestTemplateUtils.getInstance().postForObject(url, httpEntity, responseType); - long end = System.currentTimeMillis(); - if (Boolean.TRUE.equals(ThreadLocalUtil.get(DISABLE_PRINT_CACHE_KEY))) { - log.info("RESTful post请求结束 url=[{}],cost time=[{}],params=[{}]", url, end - start, JSON.toJSONString(params)); - } else { - log.info("RESTful post请求结束 url=[{}],cost time=[{}],params=[{}],responseType=[{}],result=[{}]", url, end - start, JSON.toJSONString(params), responseType, result); - } - return ResultDTO.success(result); - } catch (Exception e) { - log.error("RESTful post请求失败 url=[{}],params=[{}],responseType=[{}],errMsg:{}", url, params, responseType, e.getMessage()); - return handleFailResult(e); - } finally { - ThreadLocalUtil.clear(); - } + return restTemplate; + } + + private RestTemplateUtils() {} + + /** + * Get 请求,参数放在url中 + * + * @param url url + * @param params 参数 + * @param responseType 接收响应的类 + * @return 响应结果 + */ + public static ResultDTO get( + String url, Map params, Class responseType) { + return get(url, params, responseType, null); + } + + public static ResultDTO get( + String url, Map params, ParameterizedTypeReference responseType) { + return get(url, params, responseType, null); + } + + /** + * post + * + * @param url url + * @param params 参数 + * @param responseType 接收响应的类 + * @return 响应结果 + */ + public static ResultDTO post( + String url, Map params, Class responseType) { + return post(url, params, responseType, null); + } + + public static ResultDTO post( + String url, Map params, ParameterizedTypeReference responseType) { + return post(url, params, responseType, null); + } + + /** + * Get 请求,参数放在url中 + * + * @param url url + * @param params 参数 + * @param headers 请求头 + * @param responseType 接收响应的类 + * @return 响应结果 + */ + @SuppressWarnings("unchecked") + public static ResultDTO get( + String url, Map params, Class responseType, Map headers) { + log.info("RESTful get请求开始 url=[{}],params=[{}],responseType=[{}]", url, params, responseType); + long start = System.currentTimeMillis(); + try { + url = buildUrl(url, params); + HttpEntity> httpEntity = buildHttpEntity(params, buildHeaders(headers)); + ResponseEntity responseEntity = + RestTemplateUtils.getInstance().exchange(url, HttpMethod.GET, httpEntity, responseType); + T result = responseEntity.getBody(); + if (Boolean.TRUE.equals(ThreadLocalUtil.get(DISABLE_PRINT_CACHE_KEY))) { + log.info( + "RESTful get请求结束 url=[{}],cost time=[{}],params=[{}]", + url, + System.currentTimeMillis() - start, + params); + } else { + log.info( + "RESTful get请求结束 url=[{}],cost time=[{}],params=[{}],responseType=[{}],result=[{}]", + url, + System.currentTimeMillis() - start, + params, + responseType, + result); + } + return ResultDTO.success(result); + } catch (Exception e) { + log.error( + "RESTful get请求失败 url=[{}],params=[{}],responseType=[{}],errMsg:{}", + url, + params, + responseType, + e.getMessage()); + return handleFailResult(e); + } finally { + ThreadLocalUtil.clear(); } - - /** - * POST 请求 json参数放在body中 - * - * @param url url - * @param json 请求json参数 - * @param headers 请求头 - * @param responseType 响应映射类 - * @return 请求结果 - */ - public static ResultDTO post(String url, String json, Class responseType, Map headers) { - log.info("RESTful post请求开始 url=[{}],params=[{}],responseType=[{}]", url, json, responseType); - long start = System.currentTimeMillis(); - try { - if (null == headers) { - headers = new HashMap<>(1); - } - headers.put(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE); - HttpEntity httpEntity = buildHttpEntity(json, buildHeaders(headers)); - - T result = RestTemplateUtils.getInstance().postForObject(url, httpEntity, responseType); - long end = System.currentTimeMillis(); - if (Boolean.TRUE.equals(ThreadLocalUtil.get(DISABLE_PRINT_CACHE_KEY))) { - log.info("RESTful post请求结束 url=[{}],cost time=[{}],params=[{}]", url, end - start, json); - } else { - log.info("RESTful post请求结束 url=[{}],cost time=[{}],params=[{}],responseType=[{}],result=[{}]", url, end - start, json, responseType, result); - } - return ResultDTO.success(result); - } catch (Exception e) { - log.error("RESTful post请求失败 url=[{}],params=[{}],responseType=[{}],errMsg:{}", url, json, responseType, e.getMessage()); - return handleFailResult(e); - } finally { - ThreadLocalUtil.clear(); - } + } + + public static ResultDTO get( + String url, + Map params, + ParameterizedTypeReference responseType, + Map headers) { + log.info("RESTful get请求开始 url=[{}],params=[{}],responseType=[{}]", url, params, responseType); + long start = System.currentTimeMillis(); + try { + url = buildUrl(url, params); + HttpEntity> httpEntity = buildHttpEntity(params, buildHeaders(headers)); + ResponseEntity responseEntity = + RestTemplateUtils.getInstance().exchange(url, HttpMethod.GET, httpEntity, responseType); + + T result = responseEntity.getBody(); + if (Boolean.TRUE.equals(ThreadLocalUtil.get(DISABLE_PRINT_CACHE_KEY))) { + log.info( + "RESTful get请求结束 url=[{}],cost time=[{}],params=[{}]", + url, + System.currentTimeMillis() - start, + params); + } else { + log.info( + "RESTful get请求结束 url=[{}],cost time=[{}],params=[{}],responseType=[{}],result=[{}]", + url, + System.currentTimeMillis() - start, + params, + responseType, + result); + } + return ResultDTO.success(result); + } catch (Exception e) { + log.error( + "RESTful get请求失败 url=[{}],params=[{}],responseType=[{}],errMsg:{}", + url, + params, + responseType, + e.getMessage()); + return handleFailResult(e); + } finally { + ThreadLocalUtil.clear(); } - - /** - * post json - * - * @param url url - * @param json json str - * @param responseType rsp - * @param the type of result - * @return result - */ - public static ResultDTO post(String url, String json, ParameterizedTypeReference responseType) { - return post(url, json, responseType, null); + } + + /** + * POST 请求 参数放在body中 兼容form和json + * + * @param url url + * @param params 请求参数 + * @param headers 请求头 + * @param responseType 响应映射类 + * @return 请求结果 + */ + public static ResultDTO post( + String url, Map params, Class responseType, Map headers) { + log.info( + "RESTful post请求开始 url=[{}],params=[{}],responseType=[{}]", + url, + JSON.toJSONString(params), + responseType); + long start = System.currentTimeMillis(); + try { + HttpEntity> httpEntity = buildHttpEntity(params, buildHeaders(headers)); + + T result = RestTemplateUtils.getInstance().postForObject(url, httpEntity, responseType); + long end = System.currentTimeMillis(); + if (Boolean.TRUE.equals(ThreadLocalUtil.get(DISABLE_PRINT_CACHE_KEY))) { + log.info( + "RESTful post请求结束 url=[{}],cost time=[{}],params=[{}]", + url, + end - start, + JSON.toJSONString(params)); + } else { + log.info( + "RESTful post请求结束 url=[{}],cost time=[{}],params=[{}],responseType=[{}],result=[{}]", + url, + end - start, + JSON.toJSONString(params), + responseType, + result); + } + return ResultDTO.success(result); + } catch (Exception e) { + log.error( + "RESTful post请求失败 url=[{}],params=[{}],responseType=[{}],errMsg:{}", + url, + params, + responseType, + e.getMessage()); + return handleFailResult(e); + } finally { + ThreadLocalUtil.clear(); } - - /** - * POST 请求 json参数放在body中 - * - * @param url url - * @param json 请求json参数 - * @param responseType 响应映射类 - * @return 请求结果 - */ - public static ResultDTO post(String url, String json, Class responseType) { - return post(url, json, responseType, null); + } + + /** + * POST 请求 json参数放在body中 + * + * @param url url + * @param json 请求json参数 + * @param headers 请求头 + * @param responseType 响应映射类 + * @return 请求结果 + */ + public static ResultDTO post( + String url, String json, Class responseType, Map headers) { + log.info("RESTful post请求开始 url=[{}],params=[{}],responseType=[{}]", url, json, responseType); + long start = System.currentTimeMillis(); + try { + if (null == headers) { + headers = new HashMap<>(1); + } + headers.put(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE); + HttpEntity httpEntity = buildHttpEntity(json, buildHeaders(headers)); + + T result = RestTemplateUtils.getInstance().postForObject(url, httpEntity, responseType); + long end = System.currentTimeMillis(); + if (Boolean.TRUE.equals(ThreadLocalUtil.get(DISABLE_PRINT_CACHE_KEY))) { + log.info("RESTful post请求结束 url=[{}],cost time=[{}],params=[{}]", url, end - start, json); + } else { + log.info( + "RESTful post请求结束 url=[{}],cost time=[{}],params=[{}],responseType=[{}],result=[{}]", + url, + end - start, + json, + responseType, + result); + } + return ResultDTO.success(result); + } catch (Exception e) { + log.error( + "RESTful post请求失败 url=[{}],params=[{}],responseType=[{}],errMsg:{}", + url, + json, + responseType, + e.getMessage()); + return handleFailResult(e); + } finally { + ThreadLocalUtil.clear(); } - - /** - * post json - * - * @param url url - * @param json json str - * @param responseType rsp - * @param headers headers - * @param the type of result - * @return result - */ - public static ResultDTO post(String url, String json, ParameterizedTypeReference responseType, Map headers) { - log.info("RESTful post请求开始 url=[{}],params=[{}],responseType=[{}]", url, json, responseType); - long start = System.currentTimeMillis(); - try { - if (null == headers) { - headers = new HashMap<>(1); - } - headers.put(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE); - HttpEntity httpEntity = buildHttpEntity(json, buildHeaders(headers)); - ResponseEntity response = RestTemplateUtils.getInstance().exchange(url, HttpMethod.POST, httpEntity, responseType); - T result = response.getBody(); - long end = System.currentTimeMillis(); - if (Boolean.TRUE.equals(ThreadLocalUtil.get(DISABLE_PRINT_CACHE_KEY))) { - log.info("RESTful post请求结束 url=[{}],cost time=[{}],params=[{}]", url, end - start, json); - } else { - log.info("RESTful post请求结束 url=[{}],cost time=[{}],params=[{}],responseType=[{}],result=[{}]", url, end - start, json, responseType, result); - } - return ResultDTO.success(result); - } catch (Exception e) { - log.error("RESTful post请求失败 url=[{}],params=[{}],responseType=[{}],errMsg:{}", url, json, responseType, e.getMessage()); - return handleFailResult(e); - } finally { - ThreadLocalUtil.clear(); - } + } + + /** + * post json + * + * @param url url + * @param json json str + * @param responseType rsp + * @param the type of result + * @return result + */ + public static ResultDTO post( + String url, String json, ParameterizedTypeReference responseType) { + return post(url, json, responseType, null); + } + + /** + * POST 请求 json参数放在body中 + * + * @param url url + * @param json 请求json参数 + * @param responseType 响应映射类 + * @return 请求结果 + */ + public static ResultDTO post(String url, String json, Class responseType) { + return post(url, json, responseType, null); + } + + /** + * post json + * + * @param url url + * @param json json str + * @param responseType rsp + * @param headers headers + * @param the type of result + * @return result + */ + public static ResultDTO post( + String url, + String json, + ParameterizedTypeReference responseType, + Map headers) { + log.info("RESTful post请求开始 url=[{}],params=[{}],responseType=[{}]", url, json, responseType); + long start = System.currentTimeMillis(); + try { + if (null == headers) { + headers = new HashMap<>(1); + } + headers.put(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE); + HttpEntity httpEntity = buildHttpEntity(json, buildHeaders(headers)); + ResponseEntity response = + RestTemplateUtils.getInstance().exchange(url, HttpMethod.POST, httpEntity, responseType); + T result = response.getBody(); + long end = System.currentTimeMillis(); + if (Boolean.TRUE.equals(ThreadLocalUtil.get(DISABLE_PRINT_CACHE_KEY))) { + log.info("RESTful post请求结束 url=[{}],cost time=[{}],params=[{}]", url, end - start, json); + } else { + log.info( + "RESTful post请求结束 url=[{}],cost time=[{}],params=[{}],responseType=[{}],result=[{}]", + url, + end - start, + json, + responseType, + result); + } + return ResultDTO.success(result); + } catch (Exception e) { + log.error( + "RESTful post请求失败 url=[{}],params=[{}],responseType=[{}],errMsg:{}", + url, + json, + responseType, + e.getMessage()); + return handleFailResult(e); + } finally { + ThreadLocalUtil.clear(); } - - - public static ResultDTO post(String url, Map params, ParameterizedTypeReference responseType, Map headers) { - log.info("RESTful post请求开始 url=[{}],params=[{}],responseType=[{}]", url, JSON.toJSONString(params), responseType); - long start = System.currentTimeMillis(); - try { - HttpEntity> httpEntity = buildHttpEntity(params, buildHeaders(headers)); - - ResponseEntity response = RestTemplateUtils.getInstance().exchange(url, HttpMethod.POST, httpEntity, responseType); - T result = response.getBody(); - long end = System.currentTimeMillis(); - if (Boolean.TRUE.equals(ThreadLocalUtil.get(DISABLE_PRINT_CACHE_KEY))) { - log.info("RESTful post请求结束 url=[{}],cost time=[{}],params=[{}]", url, end - start, JSON.toJSONString(params)); - } else { - log.info("RESTful post请求结束 url=[{}],cost time=[{}],params=[{}],responseType=[{}],result=[{}]", url, end - start, JSON.toJSONString(params), responseType, result); - } - return ResultDTO.success(result); - } catch (Exception e) { - log.error("RESTful post请求失败 url=[{}],params=[{}],responseType=[{}],errMsg:{}", url, params, responseType, e.getMessage()); - return handleFailResult(e); - } finally { - ThreadLocalUtil.clear(); - } + } + + public static ResultDTO post( + String url, + Map params, + ParameterizedTypeReference responseType, + Map headers) { + log.info( + "RESTful post请求开始 url=[{}],params=[{}],responseType=[{}]", + url, + JSON.toJSONString(params), + responseType); + long start = System.currentTimeMillis(); + try { + HttpEntity> httpEntity = buildHttpEntity(params, buildHeaders(headers)); + + ResponseEntity response = + RestTemplateUtils.getInstance().exchange(url, HttpMethod.POST, httpEntity, responseType); + T result = response.getBody(); + long end = System.currentTimeMillis(); + if (Boolean.TRUE.equals(ThreadLocalUtil.get(DISABLE_PRINT_CACHE_KEY))) { + log.info( + "RESTful post请求结束 url=[{}],cost time=[{}],params=[{}]", + url, + end - start, + JSON.toJSONString(params)); + } else { + log.info( + "RESTful post请求结束 url=[{}],cost time=[{}],params=[{}],responseType=[{}],result=[{}]", + url, + end - start, + JSON.toJSONString(params), + responseType, + result); + } + return ResultDTO.success(result); + } catch (Exception e) { + log.error( + "RESTful post请求失败 url=[{}],params=[{}],responseType=[{}],errMsg:{}", + url, + params, + responseType, + e.getMessage()); + return handleFailResult(e); + } finally { + ThreadLocalUtil.clear(); } - - /** - * PUT 请求 - * - * @param url url - * @param params 请求参数 - * @param headers 请求头 - * @param responseType 响应映射类 - * @return 请求结果 - */ - public static ResultDTO put(String url, Map params, Class responseType, Map headers) { - log.info("RESTful put请求开始 url=[{}],params=[{}],responseType=[{}]", url, params, responseType); - long start = System.currentTimeMillis(); - try { - url = buildUrl(url, params); - HttpEntity> httpEntity = buildHttpEntity(params, buildHeaders(headers)); - ResponseEntity exchange = RestTemplateUtils.getInstance().exchange(url, HttpMethod.PUT, httpEntity, responseType); - T result = exchange.getBody(); - long end = System.currentTimeMillis(); - log.info("RESTful put请求结束 url=[{}],cost time=[{}],params=[{}],responseType=[{}],exchange=[{}]", url, end - start, params, responseType, exchange); - return ResultDTO.success(result); - } catch (Exception e) { - log.error("RESTful put请求失败 url=[{}],params=[{}],responseType=[{}],errMsg:{}", url, params, responseType, e.getMessage()); - return handleFailResult(e); - } + } + + /** + * PUT 请求 + * + * @param url url + * @param params 请求参数 + * @param headers 请求头 + * @param responseType 响应映射类 + * @return 请求结果 + */ + public static ResultDTO put( + String url, Map params, Class responseType, Map headers) { + log.info("RESTful put请求开始 url=[{}],params=[{}],responseType=[{}]", url, params, responseType); + long start = System.currentTimeMillis(); + try { + url = buildUrl(url, params); + HttpEntity> httpEntity = buildHttpEntity(params, buildHeaders(headers)); + ResponseEntity exchange = + RestTemplateUtils.getInstance().exchange(url, HttpMethod.PUT, httpEntity, responseType); + T result = exchange.getBody(); + long end = System.currentTimeMillis(); + log.info( + "RESTful put请求结束 url=[{}],cost time=[{}],params=[{}],responseType=[{}],exchange=[{}]", + url, + end - start, + params, + responseType, + exchange); + return ResultDTO.success(result); + } catch (Exception e) { + log.error( + "RESTful put请求失败 url=[{}],params=[{}],responseType=[{}],errMsg:{}", + url, + params, + responseType, + e.getMessage()); + return handleFailResult(e); } - - public static ResultDTO put(String url, Map params, ParameterizedTypeReference responseType, Map headers) { - log.info("RESTful put请求开始 url=[{}],params=[{}],responseType=[{}]", url, params, responseType); - long start = System.currentTimeMillis(); - - try { - url = buildUrl(url, params); - HttpEntity> httpEntity = buildHttpEntity(params, buildHeaders(headers)); - ResponseEntity exchange = RestTemplateUtils.getInstance().exchange(url, HttpMethod.PUT, httpEntity, responseType); - T result = exchange.getBody(); - log.info("RESTful put请求结束 url=[{}],cost time=[{}],params=[{}],responseType=[{}],exchange=[{}]", url, System.currentTimeMillis() - start, params, responseType, exchange); - return ResultDTO.success(result); - } catch (Exception e) { - log.error("RESTful put请求失败 url=[{}],params=[{}],responseType=[{}],errMsg:{}", url, params, responseType, e.getMessage()); - return handleFailResult(e); - } + } + + public static ResultDTO put( + String url, + Map params, + ParameterizedTypeReference responseType, + Map headers) { + log.info("RESTful put请求开始 url=[{}],params=[{}],responseType=[{}]", url, params, responseType); + long start = System.currentTimeMillis(); + + try { + url = buildUrl(url, params); + HttpEntity> httpEntity = buildHttpEntity(params, buildHeaders(headers)); + ResponseEntity exchange = + RestTemplateUtils.getInstance().exchange(url, HttpMethod.PUT, httpEntity, responseType); + T result = exchange.getBody(); + log.info( + "RESTful put请求结束 url=[{}],cost time=[{}],params=[{}],responseType=[{}],exchange=[{}]", + url, + System.currentTimeMillis() - start, + params, + responseType, + exchange); + return ResultDTO.success(result); + } catch (Exception e) { + log.error( + "RESTful put请求失败 url=[{}],params=[{}],responseType=[{}],errMsg:{}", + url, + params, + responseType, + e.getMessage()); + return handleFailResult(e); } - - /** - * DELETE 请求 参数放在url中 - * - * @param url url - * @param params 请求参数 - * @param headers 请求头 - * @param responseType 响应映射类 - * @return 请求结果 - */ - public static ResultDTO delete(String url, Map params, Class responseType, Map headers) { - log.info("RESTful delete请求开始 url=[{}],params=[{}],responseType=[{}]", url, params, responseType); - long start = System.currentTimeMillis(); - try { - url = buildUrl(url, params); - HttpEntity> httpEntity = buildHttpEntity(params, buildHeaders(headers)); - ResponseEntity exchange = RestTemplateUtils.getInstance().exchange(url, HttpMethod.DELETE, httpEntity, responseType, params); - T result = exchange.getBody(); - log.debug("RESTful delete请求结束 url=[{}],cost time=[{}],params=[{}],responseType=[{}],exchange=[{}]", url, System.currentTimeMillis() - start, params, responseType, exchange); - return ResultDTO.success(result); - } catch (Exception e) { - log.error("RESTful delete请求失败 url=[{}],params=[{}],responseType=[{}],errMsg:{}", url, params, responseType, e.getMessage()); - return handleFailResult(e); - } + } + + /** + * DELETE 请求 参数放在url中 + * + * @param url url + * @param params 请求参数 + * @param headers 请求头 + * @param responseType 响应映射类 + * @return 请求结果 + */ + public static ResultDTO delete( + String url, Map params, Class responseType, Map headers) { + log.info( + "RESTful delete请求开始 url=[{}],params=[{}],responseType=[{}]", url, params, responseType); + long start = System.currentTimeMillis(); + try { + url = buildUrl(url, params); + HttpEntity> httpEntity = buildHttpEntity(params, buildHeaders(headers)); + ResponseEntity exchange = + RestTemplateUtils.getInstance() + .exchange(url, HttpMethod.DELETE, httpEntity, responseType, params); + T result = exchange.getBody(); + log.debug( + "RESTful delete请求结束 url=[{}],cost time=[{}],params=[{}],responseType=[{}],exchange=[{}]", + url, + System.currentTimeMillis() - start, + params, + responseType, + exchange); + return ResultDTO.success(result); + } catch (Exception e) { + log.error( + "RESTful delete请求失败 url=[{}],params=[{}],responseType=[{}],errMsg:{}", + url, + params, + responseType, + e.getMessage()); + return handleFailResult(e); } - - public static ResultDTO delete(String url, Map params, ParameterizedTypeReference responseType, Map headers) { - log.info("RESTful delete请求开始 url=[{}],params=[{}],responseType=[{}]", url, params, responseType); - long start = System.currentTimeMillis(); - try { - url = buildUrl(url, params); - HttpEntity> httpEntity = buildHttpEntity(params, buildHeaders(headers)); - ResponseEntity exchange = RestTemplateUtils.getInstance().exchange(url, HttpMethod.DELETE, httpEntity, responseType, params); - T result = exchange.getBody(); - log.info("RESTful delete请求结束 url=[{}],cost time=[{}],params=[{}],responseType=[{}],exchange=[{}]", url, System.currentTimeMillis() - start, params, responseType, exchange); - return ResultDTO.success(result); - } catch (Exception e) { - log.error("RESTful delete请求失败 url=[{}],params=[{}],responseType=[{}],errMsg:{}", url, params, responseType, e.getMessage()); - return handleFailResult(e); - } + } + + public static ResultDTO delete( + String url, + Map params, + ParameterizedTypeReference responseType, + Map headers) { + log.info( + "RESTful delete请求开始 url=[{}],params=[{}],responseType=[{}]", url, params, responseType); + long start = System.currentTimeMillis(); + try { + url = buildUrl(url, params); + HttpEntity> httpEntity = buildHttpEntity(params, buildHeaders(headers)); + ResponseEntity exchange = + RestTemplateUtils.getInstance() + .exchange(url, HttpMethod.DELETE, httpEntity, responseType, params); + T result = exchange.getBody(); + log.info( + "RESTful delete请求结束 url=[{}],cost time=[{}],params=[{}],responseType=[{}],exchange=[{}]", + url, + System.currentTimeMillis() - start, + params, + responseType, + exchange); + return ResultDTO.success(result); + } catch (Exception e) { + log.error( + "RESTful delete请求失败 url=[{}],params=[{}],responseType=[{}],errMsg:{}", + url, + params, + responseType, + e.getMessage()); + return handleFailResult(e); } - - /** - * post xml请求 - * - * @param url 请求地址 - * @param data 请求数据 - * @param responseType 响应映射类 - * @return 请求结果 - */ - public static ResultDTO postXml(String url, String data, Class responseType) { - log.info("RESTful post xml 请求开始 url=[{}],data=[{}],responseType=[{}]", url, data, responseType); - long start = System.currentTimeMillis(); - try { - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_XML); - HttpEntity httpEntity = new HttpEntity<>(data, headers); - T result = RestTemplateUtils.getInstance().postForObject(url, httpEntity, responseType); - log.info("RESTful postXml请求结束 url=[{}],cost time=[{}],params=[{}],responseType=[{}],result=[{}]", url, System.currentTimeMillis() - start, data, responseType, result); - return ResultDTO.success(result); - } catch (Exception e) { - log.error("RESTful post xml 请求失败 url=[{}],data=[{}],responseType=[{}],errMsg:{}", url, data, responseType, e.getMessage()); - return handleFailResult(e); - } + } + + /** + * post xml请求 + * + * @param url 请求地址 + * @param data 请求数据 + * @param responseType 响应映射类 + * @return 请求结果 + */ + public static ResultDTO postXml(String url, String data, Class responseType) { + log.info("RESTful post xml 请求开始 url=[{}],data=[{}],responseType=[{}]", url, data, responseType); + long start = System.currentTimeMillis(); + try { + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_XML); + HttpEntity httpEntity = new HttpEntity<>(data, headers); + T result = RestTemplateUtils.getInstance().postForObject(url, httpEntity, responseType); + log.info( + "RESTful postXml请求结束 url=[{}],cost time=[{}],params=[{}],responseType=[{}],result=[{}]", + url, + System.currentTimeMillis() - start, + data, + responseType, + result); + return ResultDTO.success(result); + } catch (Exception e) { + log.error( + "RESTful post xml 请求失败 url=[{}],data=[{}],responseType=[{}],errMsg:{}", + url, + data, + responseType, + e.getMessage()); + return handleFailResult(e); } - - public static ResultDTO postXml(String url, String data, ParameterizedTypeReference responseType) { - log.info("RESTful post xml 请求开始 url=[{}],data=[{}],responseType=[{}]", url, data, responseType); - long start = System.currentTimeMillis(); - try { - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_XML); - HttpEntity httpEntity = new HttpEntity<>(data, headers); - T result = RestTemplateUtils.getInstance().exchange(url, HttpMethod.POST, httpEntity, responseType).getBody(); - log.info("RESTful postXml请求结束 url=[{}],cost time=[{}],params=[{}],responseType=[{}],result=[{}]", url, System.currentTimeMillis() - start, data, responseType, result); - return ResultDTO.success(result); - } catch (Exception e) { - log.error("RESTful post xml 请求失败 url=[{}],data=[{}],responseType=[{}],errMsg:{}", url, data, responseType, e.getMessage()); - return handleFailResult(e); - } + } + + public static ResultDTO postXml( + String url, String data, ParameterizedTypeReference responseType) { + log.info("RESTful post xml 请求开始 url=[{}],data=[{}],responseType=[{}]", url, data, responseType); + long start = System.currentTimeMillis(); + try { + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_XML); + HttpEntity httpEntity = new HttpEntity<>(data, headers); + T result = + RestTemplateUtils.getInstance() + .exchange(url, HttpMethod.POST, httpEntity, responseType) + .getBody(); + log.info( + "RESTful postXml请求结束 url=[{}],cost time=[{}],params=[{}],responseType=[{}],result=[{}]", + url, + System.currentTimeMillis() - start, + data, + responseType, + result); + return ResultDTO.success(result); + } catch (Exception e) { + log.error( + "RESTful post xml 请求失败 url=[{}],data=[{}],responseType=[{}],errMsg:{}", + url, + data, + responseType, + e.getMessage()); + return handleFailResult(e); } + } - public static String buildUrl(String host, String path) { - StringBuilder urlBuilder = new StringBuilder(host); - - if (host.endsWith("/") && path.startsWith("/")) { - urlBuilder.append(path.substring(1)); - } - if (null != path) { + public static String buildUrl(String host, String path) { + StringBuilder urlBuilder = new StringBuilder(host); - urlBuilder.append(path); - } - return urlBuilder.toString(); + if (host.endsWith("/") && path.startsWith("/")) { + urlBuilder.append(path.substring(1)); } + if (null != path) { - private static HttpEntity buildHttpEntity(T params, HttpHeaders headers) { - return new HttpEntity<>(params, headers); + urlBuilder.append(path); } + return urlBuilder.toString(); + } + private static HttpEntity buildHttpEntity(T params, HttpHeaders headers) { + return new HttpEntity<>(params, headers); + } - public static HttpHeaders buildHeaders(Map headers) { - if (CollectionUtils.isEmpty(headers)) { - return null; - } - HttpHeaders httpHeaders = new HttpHeaders(); - headers.forEach(httpHeaders::add); - return httpHeaders; + public static HttpHeaders buildHeaders(Map headers) { + if (CollectionUtils.isEmpty(headers)) { + return null; } - - public static String buildUrl(String url, Map params) { - UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url); - //如果存在參數 放在url中 - if (null != params && !params.isEmpty()) { - params.forEach(builder::queryParam); - } - return builder.build().toString(); + HttpHeaders httpHeaders = new HttpHeaders(); + headers.forEach(httpHeaders::add); + return httpHeaders; + } + + public static String buildUrl(String url, Map params) { + UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url); + // 如果存在參數 放在url中 + if (null != params && !params.isEmpty()) { + params.forEach(builder::queryParam); } - - private static ResultDTO handleFailResult(Exception ex) { - ResultDTO result; - if (ex instanceof ResourceAccessException) { - Throwable cause = ex.getCause(); - if (cause instanceof ConnectException) { - result = ResultDTO.fail(ReqResultCode.CONNECT_REFUSED.getCode(), ex.getMessage()); - } else if (cause instanceof SocketTimeoutException) { - if (cause.getMessage().toLowerCase().contains("connect")) { - result = ResultDTO.fail(ReqResultCode.CONNECT_TIMEOUT.getCode(), ex.getMessage()); - } else if (cause.getMessage().toLowerCase().contains("read")) { - result = ResultDTO.fail(ReqResultCode.READ_TIMEOUT.getCode(), ex.getMessage()); - } else { - result = ResultDTO.fail(ReqResultCode.SOCKET_TIMEOUT.getCode(), ex.getMessage()); - } - } else { - result = ResultDTO.fail(ReqResultCode.RESOURCE_REQUEST_ERROR.getCode(), ex.getMessage()); - } - } else if (ex instanceof HttpStatusCodeException) { - HttpStatusCodeException e = (HttpStatusCodeException) ex; - JSONObject object = new JSONObject(); - object.put("rspBody", e.getResponseBodyAsString()); - object.put("errMsg", e.getMessage()); - result = ResultDTO.fail(String.valueOf(e.getRawStatusCode()), object.toJSONString()); - } else if (ex instanceof UnknownContentTypeException) { - UnknownContentTypeException e = (UnknownContentTypeException) ex; - JSONObject object = new JSONObject(); - object.put("rspBody", e.getResponseBodyAsString()); - object.put("errMsg", e.getMessage()); - object.put("Content-type", e.getContentType().toString()); - object.put("headers", Objects.requireNonNull(e.getResponseHeaders()).toSingleValueMap()); - result = ResultDTO.fail(String.valueOf(e.getRawStatusCode()), object.toJSONString()); + return builder.build().toString(); + } + + private static ResultDTO handleFailResult(Exception ex) { + ResultDTO result; + if (ex instanceof ResourceAccessException) { + Throwable cause = ex.getCause(); + if (cause instanceof ConnectException) { + result = ResultDTO.fail(ReqResultCode.CONNECT_REFUSED.getCode(), ex.getMessage()); + } else if (cause instanceof SocketTimeoutException) { + if (cause.getMessage().toLowerCase().contains("connect")) { + result = ResultDTO.fail(ReqResultCode.CONNECT_TIMEOUT.getCode(), ex.getMessage()); + } else if (cause.getMessage().toLowerCase().contains("read")) { + result = ResultDTO.fail(ReqResultCode.READ_TIMEOUT.getCode(), ex.getMessage()); } else { - result = ResultDTO.fail(ReqResultCode.REQUEST_ERROR.getCode(), ex.getMessage()); + result = ResultDTO.fail(ReqResultCode.SOCKET_TIMEOUT.getCode(), ex.getMessage()); } - log.error("请求接口失败,失败原因:\n{}", result); - return result; + } else { + result = ResultDTO.fail(ReqResultCode.RESOURCE_REQUEST_ERROR.getCode(), ex.getMessage()); + } + } else if (ex instanceof HttpStatusCodeException) { + HttpStatusCodeException e = (HttpStatusCodeException) ex; + JSONObject object = new JSONObject(); + object.put("rspBody", e.getResponseBodyAsString()); + object.put("errMsg", e.getMessage()); + result = ResultDTO.fail(String.valueOf(e.getRawStatusCode()), object.toJSONString()); + } else if (ex instanceof UnknownContentTypeException) { + UnknownContentTypeException e = (UnknownContentTypeException) ex; + JSONObject object = new JSONObject(); + object.put("rspBody", e.getResponseBodyAsString()); + object.put("errMsg", e.getMessage()); + object.put("Content-type", e.getContentType().toString()); + object.put("headers", Objects.requireNonNull(e.getResponseHeaders()).toSingleValueMap()); + result = ResultDTO.fail(String.valueOf(e.getRawStatusCode()), object.toJSONString()); + } else { + result = ResultDTO.fail(ReqResultCode.REQUEST_ERROR.getCode(), ex.getMessage()); } + log.error("请求接口失败,失败原因:\n{}", result); + return result; + } - public static void withNoPrintRsp() { - ThreadLocalUtil.put(DISABLE_PRINT_CACHE_KEY, true); - } + public static void withNoPrintRsp() { + ThreadLocalUtil.put(DISABLE_PRINT_CACHE_KEY, true); + } } - diff --git a/src/main/java/com/sondertara/joya/utils/SqlUtils.java b/src/main/java/com/sondertara/joya/utils/SqlUtils.java index 9ec6947..b4fd306 100644 --- a/src/main/java/com/sondertara/joya/utils/SqlUtils.java +++ b/src/main/java/com/sondertara/joya/utils/SqlUtils.java @@ -14,263 +14,267 @@ */ @Slf4j public class SqlUtils { - /** - * 左边字段提取 - */ - public static final Pattern LEFT_COLUMN_FORMAT = Pattern.compile("^[t|T][0-9]+(.)[A-Za-z0-9]+[\\s]*[=]?|[\\s][t|T][0-9]+(.)[A-Za-z0-9]+[\\s]*[=]?"); - /** - * 带表别名的列 - */ - public static final Pattern COLUMN_WITH_TABLE_ALIAS = Pattern.compile("(?![\"'])[t|T][0-9]+(.)[A-Za-z0-9]+[\\s]*(?![\"'])"); - - private SqlUtils() { - throw new IllegalStateException("工具类,不需要实例化"); + /** 左边字段提取 */ + public static final Pattern LEFT_COLUMN_FORMAT = + Pattern.compile( + "^[t|T][0-9]+(.)[A-Za-z0-9]+[\\s]*[=]?|[\\s][t|T][0-9]+(.)[A-Za-z0-9]+[\\s]*[=]?"); + /** 带表别名的列 */ + public static final Pattern COLUMN_WITH_TABLE_ALIAS = + Pattern.compile("(?![\"'])[t|T][0-9]+(.)[A-Za-z0-9]+[\\s]*(?![\"'])"); + + private SqlUtils() { + throw new IllegalStateException("工具类,不需要实例化"); + } + + /** + * 根据查询列表SQL语句自动构造查询记录总数的SQL语句 + * + * @param strSql String + * @return String + */ + public static String buildCountSql(Object strSql) { + + StringBuilder countBuff = new StringBuilder(); + if (strSql != null) { + String sql; + if (strSql instanceof String) { + sql = (String) strSql; + } else if (strSql instanceof StringBuffer) { + sql = ((StringBuffer) strSql).toString(); + } else { + throw new IllegalArgumentException("不受支持的参数类型!"); + } + + if (containsDistinctKeywords(sql)) { + + // 查询字段 + String queryField = + sql.substring(findStrPosition(sql, "distinct") + 8, findStrPosition(sql, "from")) + .trim(); + + countBuff.append("select count(distinct ").append(queryField).append(") "); + } else { + countBuff.append("select count(*) "); + } + + countBuff.append(removeOrderBy(trimFrom(sql))); } - - /** - * 根据查询列表SQL语句自动构造查询记录总数的SQL语句 - * - * @param strSql String - * @return String - */ - public static String buildCountSql(Object strSql) { - - StringBuilder countBuff = new StringBuilder(); - if (strSql != null) { - String sql; - if (strSql instanceof String) { - sql = (String) strSql; - } else if (strSql instanceof StringBuffer) { - sql = ((StringBuffer) strSql).toString(); - } else { - throw new IllegalArgumentException("不受支持的参数类型!"); - } - - if (containsDistinctKeywords(sql)) { - - // 查询字段 - String queryField = sql.substring(findStrPosition(sql, "distinct") + 8, findStrPosition(sql, "from")).trim(); - - countBuff.append("select count(distinct ").append(queryField).append(") "); - } else { - countBuff.append("select count(*) "); - } - - countBuff.append(removeOrderBy(trimFrom(sql))); - } - return countBuff.toString(); - } - - /** - * 取sql语句从"from"之后的字符串 - * - * @param sql String - * @return String - */ - public static String trimFrom(String sql) { - String patternString = "[Ff][Rr][Oo][Mm]"; - Pattern pattern = Pattern.compile(patternString); - Matcher matcher = pattern.matcher(sql); - // 后面的字符 - return matcher.find() ? sql.substring(matcher.start()) : ""; - } - - /** - * 判断SQL语句中是否包含distinct关键字 - * - * @param sql str - * @return is contains distinct - */ - public static boolean containsDistinctKeywords(String sql) { - - Pattern pattern = Pattern.compile("\\s*" + buildRegexStr("select") + "\\s*" + buildRegexStr("distinct")); - Matcher matcher = pattern.matcher(sql); - - return matcher.find() && matcher.start() == 0; - } - - /** - * 根据字符串生成正则表达式 比如where生成[Ww][Hh][Ee][Rr]的正则表达式 - * - * @param str String - * @return String - */ - public static String buildRegexStr(String str) { - - // 转出大写 - String upperCaseStr = str.toUpperCase(); - - char[] strArr = upperCaseStr.toCharArray(); - char[] regexArr = new char[str.length() * 4]; - for (int i = 0; i < strArr.length; i++) { - regexArr[4 * i] = '['; - regexArr[4 * i + 1] = strArr[i]; - // to lower case - regexArr[4 * i + 2] = (char) (strArr[i] + 32); - regexArr[4 * i + 3] = ']'; - } - - return String.copyValueOf(regexArr); + return countBuff.toString(); + } + + /** + * 取sql语句从"from"之后的字符串 + * + * @param sql String + * @return String + */ + public static String trimFrom(String sql) { + String patternString = "[Ff][Rr][Oo][Mm]"; + Pattern pattern = Pattern.compile(patternString); + Matcher matcher = pattern.matcher(sql); + // 后面的字符 + return matcher.find() ? sql.substring(matcher.start()) : ""; + } + + /** + * 判断SQL语句中是否包含distinct关键字 + * + * @param sql str + * @return is contains distinct + */ + public static boolean containsDistinctKeywords(String sql) { + + Pattern pattern = + Pattern.compile("\\s*" + buildRegexStr("select") + "\\s*" + buildRegexStr("distinct")); + Matcher matcher = pattern.matcher(sql); + + return matcher.find() && matcher.start() == 0; + } + + /** + * 根据字符串生成正则表达式 比如where生成[Ww][Hh][Ee][Rr]的正则表达式 + * + * @param str String + * @return String + */ + public static String buildRegexStr(String str) { + + // 转出大写 + String upperCaseStr = str.toUpperCase(); + + char[] strArr = upperCaseStr.toCharArray(); + char[] regexArr = new char[str.length() * 4]; + for (int i = 0; i < strArr.length; i++) { + regexArr[4 * i] = '['; + regexArr[4 * i + 1] = strArr[i]; + // to lower case + regexArr[4 * i + 2] = (char) (strArr[i] + 32); + regexArr[4 * i + 3] = ']'; } - /** - * 替换不规则的order by 子句为" ORDER BY " - * - * @param sql String - * @return String - */ - public static String replaceOrderBy(String sql) { - String patternString = "\\s*[Oo][Rr][Dd][Ee][Rr]\\s+[Bb][Yy]\\s*"; - Pattern pattern = Pattern.compile(patternString); - Matcher matcher = pattern.matcher(sql); - // 后面的字符 - return matcher.replaceAll(" ORDER BY "); + return String.copyValueOf(regexArr); + } + + /** + * 替换不规则的order by 子句为" ORDER BY " + * + * @param sql String + * @return String + */ + public static String replaceOrderBy(String sql) { + String patternString = "\\s*[Oo][Rr][Dd][Ee][Rr]\\s+[Bb][Yy]\\s*"; + Pattern pattern = Pattern.compile(patternString); + Matcher matcher = pattern.matcher(sql); + // 后面的字符 + return matcher.replaceAll(" ORDER BY "); + } + + /** + * 替换不规则的AA 子句为" AS " + * + * @param sql String + * @return String + */ + public static String replaceAs(String sql) { + String patternString = "\\s*[Aa][Ss]\\s*"; + Pattern pattern = Pattern.compile(patternString); + Matcher matcher = pattern.matcher(sql); + return matcher.replaceAll(" AS ").trim(); + } + + /** + * 替换连续空格 为标准一个空格 + * + * @param sql sql str + * @return the single space sql srt + */ + public static String replaceSpace(String sql) { + String patternString = "\\s*( {2,})\\s*"; + Pattern pattern = Pattern.compile(patternString); + Matcher matcher = pattern.matcher(sql); + return matcher.replaceAll(" ").trim(); + } + + /** + * 格式化列,只格式化左边部分 + * + * @param sql str + * @return underLine str + */ + public static String formatColumn(String sql) { + if (StringUtils.isBlank(sql)) { + return ""; } - /** - * 替换不规则的AA 子句为" AS " - * - * @param sql String - * @return String - */ - public static String replaceAs(String sql) { - String patternString = "\\s*[Aa][Ss]\\s*"; - Pattern pattern = Pattern.compile(patternString); - Matcher matcher = pattern.matcher(sql); - return matcher.replaceAll(" AS ").trim(); - } - - /** - * 替换连续空格 为标准一个空格 - * - * @param sql sql str - * @return the single space sql srt - */ - public static String replaceSpace(String sql) { - String patternString = "\\s*( {2,})\\s*"; - Pattern pattern = Pattern.compile(patternString); - Matcher matcher = pattern.matcher(sql); - return matcher.replaceAll(" ").trim(); - } - - - /** - * 格式化列,只格式化左边部分 - * - * @param sql str - * @return underLine str - */ - public static String formatColumn(String sql) { - if (StringUtils.isBlank(sql)) { - return ""; - } - - return RegexUtils.replaceAll(sql, LEFT_COLUMN_FORMAT, m -> { - String group = m.group(); - return StringUtils.toUnderlineCase(group); + return RegexUtils.replaceAll( + sql, + LEFT_COLUMN_FORMAT, + m -> { + String group = m.group(); + return StringUtils.toUnderlineCase(group); }); + } + + /** + * 格式化列 + * + * @param sql str + * @return underLine str + */ + public static String underlineColumn(String sql) { + if (StringUtils.isBlank(sql)) { + return ""; } - /** - * 格式化列 - * - * @param sql str - * @return underLine str - */ - public static String underlineColumn(String sql) { - if (StringUtils.isBlank(sql)) { - return ""; - } - - return RegexUtils.replaceAll(sql, COLUMN_WITH_TABLE_ALIAS, m -> { - String group = m.group(); - return StringUtils.toUnderlineCase(group); + return RegexUtils.replaceAll( + sql, + COLUMN_WITH_TABLE_ALIAS, + m -> { + String group = m.group(); + return StringUtils.toUnderlineCase(group); }); + } + + /** + * 过滤 sql语句中的order by 子句 + * + * @param sql str + * @return String + */ + public static String removeOrderBy(String sql) { + String patternString = "\\sORDER\\sBY\\s[a-zA-Z0-9._,\\s]+"; + Pattern pattern = Pattern.compile(patternString); + Matcher matcher = pattern.matcher(replaceOrderBy(sql)); + return matcher.replaceAll(""); + } + + /** + * 查找匹配字符串的位置 + * + * @param sql str + * @param targetStr target + * @return index + */ + public static int findStrPosition(String sql, String targetStr) { + String patternString = buildRegexStr(targetStr); + Pattern pattern = Pattern.compile(patternString); + Matcher matcher = pattern.matcher(sql); + + return matcher.find() ? matcher.start() : -1; + } + + public static String formatSql(String sql) { + if (sql == null) { + return null; } + return SqlFormatter.format(sql); + } - - /** - * 过滤 sql语句中的order by 子句 - * - * @param sql str - * @return String - */ - public static String removeOrderBy(String sql) { - String patternString = "\\sORDER\\sBY\\s[a-zA-Z0-9._,\\s]+"; - Pattern pattern = Pattern.compile(patternString); - Matcher matcher = pattern.matcher(replaceOrderBy(sql)); - return matcher.replaceAll(""); + public static String formatSql(NativeSqlQuery sql) { + if (sql == null) { + return null; } - - /** - * 查找匹配字符串的位置 - * - * @param sql str - * @param targetStr target - * @return index - */ - public static int findStrPosition(String sql, String targetStr) { - String patternString = buildRegexStr(targetStr); - Pattern pattern = Pattern.compile(patternString); - Matcher matcher = pattern.matcher(sql); - - return matcher.find() ? matcher.start() : -1; + return sql.toFormattedSql(); + } + + /** + * format column name + * + *

t0.userName ->t0.user_name t0.userId AA user -> t0.user_id AS user + * + * @param columnName name + * @return formatted name + */ + public static String warpColumn(String columnName) { + if (null == columnName) { + return null; } + String column = replaceAs(columnName); + // 有AS + int asIndex = column.indexOf("AS"); - public static String formatSql(String sql) { - if (sql == null) { - return null; - } - return SqlFormatter.format(sql); + String asPart = null; + if (asIndex > 1 && asIndex < column.length()) { + asPart = StringUtils.trim(column.substring(asIndex + 2)); + column = StringUtils.trim(column.substring(0, asIndex - 1)); } - - public static String formatSql(NativeSqlQuery sql) { - if (sql == null) { - return null; - } - return sql.toFormattedSql(); + // 有别名 + int index = column.indexOf("."); + StringBuilder sb; + if (index > -1) { + sb = new StringBuilder(column.substring(0, index)); + sb.append("."); + String col = column.substring(index + 1); + sb.append(StringUtils.toUnderlineCase(col)); + } else { + sb = new StringBuilder(StringUtils.toUnderlineCase(column)); + sb.append(asPart); } - - /** - * format column name - *

- * t0.userName ->t0.user_name - * t0.userId AA user -> t0.user_id AS user - * - * @param columnName name - * @return formatted name - */ - public static String warpColumn(String columnName) { - if (null == columnName) { - return null; - } - String column = replaceAs(columnName); - // 有AS - - int asIndex = column.indexOf("AS"); - - String asPart = null; - if (asIndex > 1 && asIndex < column.length()) { - asPart = StringUtils.trim(column.substring(asIndex + 2)); - column = StringUtils.trim(column.substring(0, asIndex - 1)); - } - // 有别名 - int index = column.indexOf("."); - StringBuilder sb; - if (index > -1) { - sb = new StringBuilder(column.substring(0, index)); - sb.append("."); - String col = column.substring(index + 1); - sb.append(StringUtils.toUnderlineCase(col)); - } else { - sb = new StringBuilder(StringUtils.toUnderlineCase(column)); - sb.append(asPart); - } - if (null != asPart) { - sb.append(" AS "); - sb.append(asPart); - } - return sb.toString(); + if (null != asPart) { + sb.append(" AS "); + sb.append(asPart); } + return sb.toString(); + } } diff --git a/src/main/java/com/sondertara/joya/utils/ThreadLocalUtil.java b/src/main/java/com/sondertara/joya/utils/ThreadLocalUtil.java index e0c3e64..f45376f 100644 --- a/src/main/java/com/sondertara/joya/utils/ThreadLocalUtil.java +++ b/src/main/java/com/sondertara/joya/utils/ThreadLocalUtil.java @@ -11,40 +11,39 @@ * @since 0.0.7 */ public class ThreadLocalUtil { - private static final ThreadLocal> THREAD_CONTEXT = new MapThreadLocal(); + private static final ThreadLocal> THREAD_CONTEXT = new MapThreadLocal(); - private ThreadLocalUtil() { - } + private ThreadLocalUtil() {} - private static Map getContextMap() { - return THREAD_CONTEXT.get(); - } + private static Map getContextMap() { + return THREAD_CONTEXT.get(); + } - public static Object get(String key) { - return getContextMap().get(key); - } + public static Object get(String key) { + return getContextMap().get(key); + } - public static void put(String key, Object value) { - getContextMap().put(key, value); - } + public static void put(String key, Object value) { + getContextMap().put(key, value); + } - public static void remove(String key) { - getContextMap().remove(key); - } + public static void remove(String key) { + getContextMap().remove(key); + } - public static void clear() { - THREAD_CONTEXT.remove(); - } + public static void clear() { + THREAD_CONTEXT.remove(); + } - private static class MapThreadLocal extends ThreadLocal> { + private static class MapThreadLocal extends ThreadLocal> { + @Override + protected Map initialValue() { + return new HashMap(8) { @Override - protected Map initialValue() { - return new HashMap(8) { - @Override - public Object put(String key, Object value) { - return super.put(key, value); - } - }; + public Object put(String key, Object value) { + return super.put(key, value); } + }; } + } } diff --git a/src/main/java/com/sondertara/joya/utils/cache/GuavaAbstractLoadingCache.java b/src/main/java/com/sondertara/joya/utils/cache/GuavaAbstractLoadingCache.java index a932fc3..a6b9773 100644 --- a/src/main/java/com/sondertara/joya/utils/cache/GuavaAbstractLoadingCache.java +++ b/src/main/java/com/sondertara/joya/utils/cache/GuavaAbstractLoadingCache.java @@ -11,8 +11,7 @@ import java.util.concurrent.TimeUnit; /** - * 抽象Guava缓存类、缓存模板。 - * 子类需要实现fetchData(key),从数据库或其他数据源(如Redis)中获取数据。 + * 抽象Guava缓存类、缓存模板。 子类需要实现fetchData(key),从数据库或其他数据源(如Redis)中获取数据。 * 子类调用getValue(key)方法,从缓存中获取数据,并处理不同的异常,比如value为null时的InvalidCacheLoadException异常。 * * @param key 类型 @@ -23,134 +22,124 @@ @Slf4j public abstract class GuavaAbstractLoadingCache { - - /** - * time unit of second - */ - private final TimeUnit timeUnit = TimeUnit.SECONDS; - /** - * 最大缓存条数,子类在构造方法中调用setMaximumSize(int size)来更改 - */ - private int maximumSize = 1000; - /** - * 数据存在时长,子类在构造方法中调用setExpireAfterWriteDuration(int duration)来更改 - */ - private int expireAfterWriteDuration = 60; - /** - * Cache初始化或被重置的时间 - */ - private Date resetTime; - /** - * 历史最高记录数 - */ - private long highestSize = 0; - /** - * 创造历史记录的时间 - */ - private Date highestTime; - - private volatile LoadingCache cache; - - /** - * 通过调用getCache().get(key)来获取数据 - * - * @return cache - */ - private LoadingCache getCache() { - //使用双重校验锁保证只有一个cache实例 + /** time unit of second */ + private final TimeUnit timeUnit = TimeUnit.SECONDS; + /** 最大缓存条数,子类在构造方法中调用setMaximumSize(int size)来更改 */ + private int maximumSize = 1000; + /** 数据存在时长,子类在构造方法中调用setExpireAfterWriteDuration(int duration)来更改 */ + private int expireAfterWriteDuration = 60; + /** Cache初始化或被重置的时间 */ + private Date resetTime; + /** 历史最高记录数 */ + private long highestSize = 0; + /** 创造历史记录的时间 */ + private Date highestTime; + + private volatile LoadingCache cache; + + /** + * 通过调用getCache().get(key)来获取数据 + * + * @return cache + */ + private LoadingCache getCache() { + // 使用双重校验锁保证只有一个cache实例 + if (cache == null) { + synchronized (this) { if (cache == null) { - synchronized (this) { - if (cache == null) { - cache = CacheBuilder.newBuilder().maximumSize(maximumSize).expireAfterWrite(expireAfterWriteDuration, timeUnit).recordStats().build(new CacheLoader() { + cache = + CacheBuilder.newBuilder() + .maximumSize(maximumSize) + .expireAfterWrite(expireAfterWriteDuration, timeUnit) + .recordStats() + .build( + new CacheLoader() { @Override public V load(@Nonnull K key) { - return fetchData(key); + return fetchData(key); } - }); - this.resetTime = new Date(); - this.highestTime = new Date(); - log.debug("本地缓存{}初始化成功", this.getClass().getSimpleName()); - } - } - } - - return cache; - } - - public void put(K key, V value) { - getCache().put(key, value); - } - - /** - * 根据key从数据库或其他数据源中获取一个value,并被自动保存到缓存中。 - * - * @param key key - * @return value, 连同key一起被加载到缓存中的。 - */ - protected abstract V fetchData(K key); - - - /** - * 从缓存中获取数据(第一次自动调用fetchData从外部获取数据),并处理异常 - * - * @param key key - * @return Value - * @throws ExecutionException e - */ - protected V getValue(K key) throws ExecutionException { - V result = getCache().get(key); - if (getCache().size() > highestSize) { - highestSize = getCache().size(); - highestTime = new Date(); + }); + this.resetTime = new Date(); + this.highestTime = new Date(); + log.debug("本地缓存{}初始化成功", this.getClass().getSimpleName()); } - return result; - - } - - public void invalidateAll() { - getCache().invalidateAll(); - } - - public void invalidate(K key) { - getCache().invalidate(key); - } - - public long getHighestSize() { - return highestSize; - } - - public Date getHighestTime() { - return highestTime; - } - - public Date getResetTime() { - return resetTime; - } - - - public int getMaximumSize() { - return maximumSize; - } - - /** - * 设置最大缓存条数 - * - * @param maximumSize max cache size - */ - public void setMaximumSize(int maximumSize) { - this.maximumSize = maximumSize; - } - - public int getExpireAfterWriteDuration() { - return expireAfterWriteDuration; + } } - /** - * 设置数据存在时长(second) - * - * @param expireAfterWriteDuration e - */ - public void setExpireAfterWriteDuration(int expireAfterWriteDuration) { - this.expireAfterWriteDuration = expireAfterWriteDuration; + return cache; + } + + public void put(K key, V value) { + getCache().put(key, value); + } + + /** + * 根据key从数据库或其他数据源中获取一个value,并被自动保存到缓存中。 + * + * @param key key + * @return value, 连同key一起被加载到缓存中的。 + */ + protected abstract V fetchData(K key); + + /** + * 从缓存中获取数据(第一次自动调用fetchData从外部获取数据),并处理异常 + * + * @param key key + * @return Value + * @throws ExecutionException e + */ + protected V getValue(K key) throws ExecutionException { + V result = getCache().get(key); + if (getCache().size() > highestSize) { + highestSize = getCache().size(); + highestTime = new Date(); } -} \ No newline at end of file + return result; + } + + public void invalidateAll() { + getCache().invalidateAll(); + } + + public void invalidate(K key) { + getCache().invalidate(key); + } + + public long getHighestSize() { + return highestSize; + } + + public Date getHighestTime() { + return highestTime; + } + + public Date getResetTime() { + return resetTime; + } + + public int getMaximumSize() { + return maximumSize; + } + + /** + * 设置最大缓存条数 + * + * @param maximumSize max cache size + */ + public void setMaximumSize(int maximumSize) { + this.maximumSize = maximumSize; + } + + public int getExpireAfterWriteDuration() { + return expireAfterWriteDuration; + } + + /** + * 设置数据存在时长(second) + * + * @param expireAfterWriteDuration e + */ + public void setExpireAfterWriteDuration(int expireAfterWriteDuration) { + this.expireAfterWriteDuration = expireAfterWriteDuration; + } +} diff --git a/src/main/java/com/sondertara/joya/utils/cache/ILocalCache.java b/src/main/java/com/sondertara/joya/utils/cache/ILocalCache.java index 6c64aa3..4587dd9 100644 --- a/src/main/java/com/sondertara/joya/utils/cache/ILocalCache.java +++ b/src/main/java/com/sondertara/joya/utils/cache/ILocalCache.java @@ -11,18 +11,18 @@ */ public interface ILocalCache { - /** - * 从缓存中获取数据 - * - * @param key key - * @return value - */ - Optional get(K key); + /** + * 从缓存中获取数据 + * + * @param key key + * @return value + */ + Optional get(K key); - /** - * 从缓存中获取数据 - * - * @param key key - */ - void remove(K key); -} \ No newline at end of file + /** + * 从缓存中获取数据 + * + * @param key key + */ + void remove(K key); +} diff --git a/src/main/java/com/sondertara/joya/utils/idgenerate/IdGen.java b/src/main/java/com/sondertara/joya/utils/idgenerate/IdGen.java index f593352..6466ee5 100644 --- a/src/main/java/com/sondertara/joya/utils/idgenerate/IdGen.java +++ b/src/main/java/com/sondertara/joya/utils/idgenerate/IdGen.java @@ -15,51 +15,42 @@ */ public class IdGen implements IdentifierGenerator { - private static final SecureRandom random = new SecureRandom(); - private static IdWorker idWorker = new IdWorker(-1, -1); - - /** - * Change the snowflake workId and datacenterId - * - * @param workerId workId - * @param datacenterId datacenterId - */ - public static void setIdWorker(int workerId, int datacenterId) { - idWorker = new IdWorker(workerId, datacenterId); - } - - /** - * 生成UUID, 中间无-分割 - */ - public static String uuid() { - return UUID.randomUUID().toString().replaceAll("-", ""); - } - - /** - * 使用SecureRandom随机生成Long - */ - public static long randomLong() { - return Math.abs(random.nextLong()); - } - - /** - * 使用snowflake生成18位唯一编号 - */ - public static long snowflake() { - return idWorker.nextId(); - } - - /** - * Generate the id with 18 length - * 获取新唯一编号(18位数值) - * 来自于twitter项目snowflake的id产生方案,全局唯一,时间有序。 - * 64位ID (42(毫秒)+5(机器ID)+5(业务编码)+12(重复累加)) - */ - @Override - public Serializable generate(SharedSessionContractImplementor sharedSessionContractImplementor, Object o) throws HibernateException { - return idWorker.nextId(); - } + private static final SecureRandom SECURE_RANDOM = new SecureRandom(); + private static IdWorker idWorker = new IdWorker(-1, -1); + + /** + * Change the snowflake workId and datacenterId + * + * @param workerId workId + * @param datacenterId datacenterId + */ + public static void setIdWorker(int workerId, int datacenterId) { + idWorker = new IdWorker(workerId, datacenterId); + } + + /** 生成UUID, 中间无-分割 */ + public static String uuid() { + return UUID.randomUUID().toString().replaceAll("-", ""); + } + + /** 使用SecureRandom随机生成Long */ + public static long randomLong() { + return Math.abs(SECURE_RANDOM.nextLong()); + } + + /** 使用snowflake生成18位唯一编号 */ + public static long snowflake() { + return idWorker.nextId(); + } + + /** + * Generate the id with 18 length 获取新唯一编号(18位数值) 来自于twitter项目snowflake的id产生方案,全局唯一,时间有序。 64位ID + * (42(毫秒)+5(机器ID)+5(业务编码)+12(重复累加)) + */ + @Override + public Serializable generate( + SharedSessionContractImplementor sharedSessionContractImplementor, Object o) + throws HibernateException { + return idWorker.nextId(); + } } - - - diff --git a/src/main/java/com/sondertara/joya/utils/idgenerate/IdWorker.java b/src/main/java/com/sondertara/joya/utils/idgenerate/IdWorker.java index 28f7488..b360557 100644 --- a/src/main/java/com/sondertara/joya/utils/idgenerate/IdWorker.java +++ b/src/main/java/com/sondertara/joya/utils/idgenerate/IdWorker.java @@ -1,109 +1,105 @@ -/** - * Copyright (c) 2013-Now http://jeesite.com All rights reserved. - */ +/** Copyright (c) 2013-Now http://jeesite.com All rights reserved. */ package com.sondertara.joya.utils.idgenerate; import java.util.Random; /** - * 来自于twitter项目snowflake的id产生方案,全局唯一,时间有序。 - * 64位ID (42(毫秒)+5(机器ID)+5(业务编码)+12(重复累加)) + * 来自于twitter项目snowflake的id产生方案,全局唯一,时间有序。 64位ID (42(毫秒)+5(机器ID)+5(业务编码)+12(重复累加)) * https://github.com/twitter/snowflake/blob/scala_28/src/main/ * scala/com/twitter/service/snowflake/IdWorker2.scala */ public class IdWorker { - private final static long twepoch = 1288834974657L; - // 机器标识位数 - private final static long workerIdBits = 5L; - // 数据中心标识位数 - private final static long datacenterIdBits = 5L; - // 机器ID最大值 - private final static long maxWorkerId = ~(-1L << workerIdBits); - // 数据中心ID最大值 - private final static long maxDatacenterId = ~(-1L << datacenterIdBits); - // 毫秒内自增位 - private final static long sequenceBits = 12L; - // 机器ID偏左移12位 - private final static long workerIdShift = sequenceBits; - // 数据中心ID左移17位 - private final static long datacenterIdShift = sequenceBits + workerIdBits; - // 时间毫秒左移22位 - private final static long timestampLeftShift = sequenceBits + workerIdBits - + datacenterIdBits; + private static final long twepoch = 1288834974657L; + // 机器标识位数 + private static final long workerIdBits = 5L; + // 数据中心标识位数 + private static final long datacenterIdBits = 5L; + // 机器ID最大值 + private static final long maxWorkerId = ~(-1L << workerIdBits); + // 数据中心ID最大值 + private static final long maxDatacenterId = ~(-1L << datacenterIdBits); + // 毫秒内自增位 + private static final long sequenceBits = 12L; + // 机器ID偏左移12位 + private static final long workerIdShift = sequenceBits; + // 数据中心ID左移17位 + private static final long datacenterIdShift = sequenceBits + workerIdBits; + // 时间毫秒左移22位 + private static final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits; - private final static long sequenceMask = ~(-1L << sequenceBits); + private static final long sequenceMask = ~(-1L << sequenceBits); - private static long lastTimestamp = -1L; + private static long lastTimestamp = -1L; - private long sequence = 0L; - private long workerId = 1; - private long datacenterId = 1; + private long sequence = 0L; + private long workerId = 1; + private long datacenterId = 1; - public IdWorker(long workerId, long datacenterId) { - if (workerId > maxWorkerId || workerId < 0) { - if (workerId == -1) { - workerId = new Random().nextInt((int) maxWorkerId); - } else { - throw new IllegalArgumentException( - "worker Id can't be greater than %d or less than 0"); - } - } else { - this.workerId = workerId; - } - if (datacenterId > maxDatacenterId || datacenterId < 0) { - if (datacenterId == -1) { - datacenterId = new Random().nextInt((int) maxDatacenterId); - } else { - throw new IllegalArgumentException( - "datacenter Id can't be greater than %d or less than 0"); - } - } else { - this.datacenterId = datacenterId; - } + public IdWorker(long workerId, long datacenterId) { + if (workerId > maxWorkerId || workerId < 0) { + if (workerId == -1) { + workerId = new Random().nextInt((int) maxWorkerId); + } else { + throw new IllegalArgumentException("worker Id can't be greater than %d or less than 0"); + } + } else { + this.workerId = workerId; } + if (datacenterId > maxDatacenterId || datacenterId < 0) { + if (datacenterId == -1) { + datacenterId = new Random().nextInt((int) maxDatacenterId); + } else { + throw new IllegalArgumentException("datacenter Id can't be greater than %d or less than 0"); + } + } else { + this.datacenterId = datacenterId; + } + } - public synchronized long nextId() { - long timestamp = timeGen(); - if (timestamp < lastTimestamp) { - try { - throw new Exception( - "Clock moved backwards. Refusing to generate id for " - + (lastTimestamp - timestamp) + " milliseconds"); - } catch (Exception e) { - e.printStackTrace(); - } - } - - if (lastTimestamp == timestamp) { - // 当前毫秒内,则+1 - sequence = (sequence + 1) & sequenceMask; - if (sequence == 0) { - // 当前毫秒内计数满了,则等待下一秒 - timestamp = tilNextMillis(lastTimestamp); - } - } else { - sequence = 0; - } - lastTimestamp = timestamp; - // ID偏移组合生成最终的ID,并返回ID - long nextId = ((timestamp - twepoch) << timestampLeftShift) - | (datacenterId << datacenterIdShift) - | (workerId << workerIdShift) | sequence; - - return nextId; + public synchronized long nextId() { + long timestamp = timeGen(); + if (timestamp < lastTimestamp) { + try { + throw new Exception( + "Clock moved backwards. Refusing to generate id for " + + (lastTimestamp - timestamp) + + " milliseconds"); + } catch (Exception e) { + e.printStackTrace(); + } } - private long tilNextMillis(final long lastTimestamp) { - long timestamp = timeGen(); - while (timestamp <= lastTimestamp) { - timestamp = timeGen(); - } - return timestamp; + if (lastTimestamp == timestamp) { + // 当前毫秒内,则+1 + sequence = (sequence + 1) & sequenceMask; + if (sequence == 0) { + // 当前毫秒内计数满了,则等待下一秒 + timestamp = tilNextMillis(lastTimestamp); + } + } else { + sequence = 0; } + lastTimestamp = timestamp; + // ID偏移组合生成最终的ID,并返回ID + long nextId = + ((timestamp - twepoch) << timestampLeftShift) + | (datacenterId << datacenterIdShift) + | (workerId << workerIdShift) + | sequence; + + return nextId; + } - private long timeGen() { - return System.currentTimeMillis(); + private long tilNextMillis(final long lastTimestamp) { + long timestamp = timeGen(); + while (timestamp <= lastTimestamp) { + timestamp = timeGen(); } + return timestamp; + } -} \ No newline at end of file + private long timeGen() { + return System.currentTimeMillis(); + } +} diff --git a/src/test/java/com/sondertara/joya/NativeQueryTest.java b/src/test/java/com/sondertara/joya/NativeQueryTest.java index 49a4fcf..65adbc2 100644 --- a/src/test/java/com/sondertara/joya/NativeQueryTest.java +++ b/src/test/java/com/sondertara/joya/NativeQueryTest.java @@ -1,15 +1,13 @@ package com.sondertara.joya; - import com.sondertara.joya.core.query.pagination.PageQueryParam; import org.junit.jupiter.api.Test; public class NativeQueryTest { - @Test - public void testQuery() { - PageQueryParam param = new PageQueryParam(); - param.column(); - } - + @Test + public void testQuery() { + PageQueryParam param = new PageQueryParam(); + param.column(); + } }