diff --git a/uno-core/src/main/java/cc/allio/uno/core/bean/BeanInfoWrapper.java b/uno-core/src/main/java/cc/allio/uno/core/bean/BeanInfoWrapper.java index 1cd0b232..786896b1 100644 --- a/uno-core/src/main/java/cc/allio/uno/core/bean/BeanInfoWrapper.java +++ b/uno-core/src/main/java/cc/allio/uno/core/bean/BeanInfoWrapper.java @@ -1,12 +1,12 @@ package cc.allio.uno.core.bean; +import cc.allio.uno.core.reflect.ReflectTools; import cc.allio.uno.core.type.TypeValue; import cc.allio.uno.core.type.Types; -import cc.allio.uno.core.util.ClassUtils; +import cc.allio.uno.core.util.Values; import lombok.Getter; import lombok.NonNull; import lombok.extern.slf4j.Slf4j; -import org.checkerframework.checker.units.qual.K; import org.springframework.util.Assert; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -15,18 +15,19 @@ import java.beans.IntrospectionException; import java.beans.Introspector; import java.beans.PropertyDescriptor; -import java.lang.reflect.Array; +import java.util.Arrays; +import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; -import java.util.stream.Stream; /** * 增强对Bean对象的操作。禁止在Bean上添加{@link lombok.experimental.Accessors}的注解 *

required

*
    - *
  1. Bean必须要是Public
  2. + *
  3. bean must visibility is public
  4. + *
  5. bean must be has setter and getter methods
  6. *
* * @author j.x @@ -63,6 +64,29 @@ public Flux findAll() { }); } + /** + * find all property + * + * @return the property list + */ + public List properties() { + AtomicReference> ref = new AtomicReference<>(); + findAll().collectList().doOnNext(ref::set).subscribe(); + return ref.get(); + } + + /** + * find all property name + * + * @return the name list + */ + public List names() { + return Arrays.stream(beanInfo.getPropertyDescriptors()) + .map(PropertyDescriptor::getName) + .filter(name -> !"class".equals(name)) + .toList(); + } + /** * 根据字段名称查找这个字段对应的Descriptor * @@ -214,13 +238,12 @@ public synchronized K setCoverageForce(K target, String name, bool public synchronized Mono setCoverage(K target, String name, boolean forceCoverage, Object... value) { Assert.notNull(name, "target must not null"); return findByName(name) - .flatMap(descriptor -> - write(target, descriptor, forceCoverage, value) - .onErrorContinue((error, o) -> { - if (log.isWarnEnabled()) { - log.warn("target {} setValue field {} value error setValue empty", target.getClass().getSimpleName(), name); - } - })); + .flatMap(descriptor -> write(target, descriptor, forceCoverage, value)) + .onErrorContinue((error, o) -> { + if (log.isWarnEnabled()) { + log.warn("target {} setValue field {} value error setValue empty", target.getClass().getSimpleName(), name); + } + }); } /** @@ -260,27 +283,15 @@ private Mono read(Object target, PropertyDescriptor descriptor) { private Mono write(K target, PropertyDescriptor descriptor, boolean forceCoverage, Object... args) { Mono writeMono = Mono.justOrEmpty(descriptor.getWriteMethod()) .flatMap(writeMethod -> - TypeValue.of(writeMethod.getParameterTypes(), args) - .map(TypeValue::tryTransfer) + TypeValue.of(writeMethod.getParameterTypes(), args, () -> ReflectTools.drawn(writeMethod)) + .map(TypeValue::tryConvert) .collectList() .flatMap(values -> { try { Class propertyType = descriptor.getPropertyType(); if (Types.isArray(propertyType)) { - // 数组赋值 - Object[] arrayValues = values.stream() - .flatMap(o -> { - if (Types.isArray(o.getClass())) { - return Stream.of((Object[]) o); - } - return Stream.empty(); - }) - .toArray(Object[]::new); - Object o = Array.newInstance(ClassUtils.getArrayClassType(propertyType), arrayValues.length); - for (int i = 0; i < arrayValues.length; i++) { - Array.set(o, i, arrayValues[i]); - } - writeMethod.invoke(target, o); + Object[] arrayValues = Values.expandCollection(values); + writeMethod.invoke(target, arrayValues); } else { writeMethod.invoke(target, values.toArray()); } @@ -290,8 +301,7 @@ private Mono write(K target, PropertyDescriptor descriptor, boo } } return Mono.just(target); - }) - ); + })); if (forceCoverage) { return writeMono; } diff --git a/uno-core/src/main/java/cc/allio/uno/core/metadata/convert/AbstractRichConverter.java b/uno-core/src/main/java/cc/allio/uno/core/metadata/convert/AbstractRichConverter.java index bc2e105a..172dff75 100644 --- a/uno-core/src/main/java/cc/allio/uno/core/metadata/convert/AbstractRichConverter.java +++ b/uno-core/src/main/java/cc/allio/uno/core/metadata/convert/AbstractRichConverter.java @@ -85,7 +85,7 @@ protected Mono executeAssignmentAction(String name, Class type = mappingField.getType(); // 尝试进行类型转换 if (type != null) { - setter = new TypeValue(type, setter).tryTransfer(); + setter = new TypeValue(type, setter).tryConvert(); } // 设置值在values Object setValue = setter; diff --git a/uno-core/src/main/java/cc/allio/uno/core/reflect/BinaryClassKey.java b/uno-core/src/main/java/cc/allio/uno/core/reflect/BinaryClassKey.java new file mode 100644 index 00000000..6c3b87a7 --- /dev/null +++ b/uno-core/src/main/java/cc/allio/uno/core/reflect/BinaryClassKey.java @@ -0,0 +1,12 @@ +package cc.allio.uno.core.reflect; + +import lombok.AllArgsConstructor; +import lombok.Data; + +@Data +@AllArgsConstructor(staticName = "of") +public class BinaryClassKey { + + private final Class cls1; + private final Class cls2; +} diff --git a/uno-core/src/main/java/cc/allio/uno/core/reflect/DrawnClass.java b/uno-core/src/main/java/cc/allio/uno/core/reflect/DrawnClass.java new file mode 100644 index 00000000..888ae275 --- /dev/null +++ b/uno-core/src/main/java/cc/allio/uno/core/reflect/DrawnClass.java @@ -0,0 +1,57 @@ +package cc.allio.uno.core.reflect; + +import cc.allio.uno.core.util.ObjectUtils; +import com.google.common.collect.Lists; + +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.List; + +/** + * Drawn to class + * + * @author j.x + * @date 2024/4/4 17:59 + * @since 1.1.8 + */ +public class DrawnClass implements DrawnGeneric> { + + @Override + public ParameterizedFinder drawn(Class reflectType) { + List parameterizedTypes = drawnClass(reflectType); + return new ParameterizedFinder(reflectType, parameterizedTypes); + } + + /** + * 从给定的Class对象中获取{@link ParameterizedType}类型,该方法将会递归查找所有范型父类以及范型接口 + * + * @param reflectType the reflection class + * @return the {@link ParameterizedType} list + */ + List drawnClass(Class reflectType) { + List types = Lists.newArrayList(); + Type genericSuperclass = reflectType.getGenericSuperclass(); + if (genericSuperclass != null) { + if (genericSuperclass instanceof Class superClass && !Object.class.isAssignableFrom(superClass)) { + List superParameterizedType = drawnClass(superClass); + types.addAll(superParameterizedType); + } + if (genericSuperclass instanceof ParameterizedType parameterizedSuperclass) { + types.add(parameterizedSuperclass); + } + } + Type[] genericInterfaces = reflectType.getGenericInterfaces(); + if (ObjectUtils.isNotEmpty(genericInterfaces)) { + for (Type genericInterface : genericInterfaces) { + if (genericInterface instanceof Class superInterface) { + List superParameterizedType = drawnClass(superInterface); + types.addAll(superParameterizedType); + } + if (genericInterface instanceof ParameterizedType parameterizedType) { + types.add(parameterizedType); + } + } + } + return types; + } +} diff --git a/uno-core/src/main/java/cc/allio/uno/core/reflect/DrawnField.java b/uno-core/src/main/java/cc/allio/uno/core/reflect/DrawnField.java new file mode 100644 index 00000000..d088b4a3 --- /dev/null +++ b/uno-core/src/main/java/cc/allio/uno/core/reflect/DrawnField.java @@ -0,0 +1,27 @@ +package cc.allio.uno.core.reflect; + +import com.google.common.collect.Lists; + +import java.lang.reflect.Field; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.Collections; + +/** + * Drawn to {@link Field} + * + * @author j.x + * @date 2024/4/4 18:00 + * @since 1.1.8 + */ +public class DrawnField implements DrawnGeneric { + + @Override + public ParameterizedFinder drawn(Field reflectType) { + Type genericType = reflectType.getGenericType(); + if (genericType instanceof ParameterizedType parameterizedType) { + return new ParameterizedFinder(reflectType, Lists.newArrayList(parameterizedType)); + } + return new ParameterizedFinder(reflectType, Collections.emptyList()); + } +} diff --git a/uno-core/src/main/java/cc/allio/uno/core/reflect/DrawnGeneric.java b/uno-core/src/main/java/cc/allio/uno/core/reflect/DrawnGeneric.java new file mode 100644 index 00000000..866b8e49 --- /dev/null +++ b/uno-core/src/main/java/cc/allio/uno/core/reflect/DrawnGeneric.java @@ -0,0 +1,22 @@ +package cc.allio.uno.core.reflect; + +import java.lang.reflect.Method; +import java.lang.reflect.ParameterizedType; + +/** + * drawn reflection type to actual generic type + * + * @author j.x + * @date 2024/4/4 17:58 + * @since 1.1.8 + */ +public interface DrawnGeneric { + + /** + * returns {@link ParameterizedType} of list base on reflect type. + * + * @param reflectType like as {@link Class}, {@link Method} ... + * @return the {@link ParameterizedType} list + */ + ParameterizedFinder drawn(T reflectType); +} diff --git a/uno-core/src/main/java/cc/allio/uno/core/reflect/DrawnMethod.java b/uno-core/src/main/java/cc/allio/uno/core/reflect/DrawnMethod.java new file mode 100644 index 00000000..3505eac2 --- /dev/null +++ b/uno-core/src/main/java/cc/allio/uno/core/reflect/DrawnMethod.java @@ -0,0 +1,36 @@ +package cc.allio.uno.core.reflect; + +import com.google.common.collect.Streams; + +import java.lang.reflect.Method; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.List; +import java.util.stream.Stream; + +/** + * Drawn to method + * + * @author j.x + * @date 2024/4/4 18:00 + * @since 1.1.8 + */ +public class DrawnMethod implements DrawnGeneric { + + @Override + public ParameterizedFinder drawn(Method reflectType) { + Type genericReturnType = reflectType.getGenericReturnType(); + Type[] genericExceptionTypes = reflectType.getGenericExceptionTypes(); + Type[] genericParameterTypes = reflectType.getGenericParameterTypes(); + List parameterizedTypes = + Streams.concat( + Stream.of(genericReturnType), + Stream.of(genericExceptionTypes), + Stream.of(genericParameterTypes) + ) + .filter(type -> ParameterizedType.class.isAssignableFrom(type.getClass())) + .map(ParameterizedType.class::cast) + .toList(); + return new ParameterizedFinder(reflectType, parameterizedTypes); + } +} diff --git a/uno-core/src/main/java/cc/allio/uno/core/reflect/ParameterizedFinder.java b/uno-core/src/main/java/cc/allio/uno/core/reflect/ParameterizedFinder.java new file mode 100644 index 00000000..0ecd225d --- /dev/null +++ b/uno-core/src/main/java/cc/allio/uno/core/reflect/ParameterizedFinder.java @@ -0,0 +1,109 @@ +package cc.allio.uno.core.reflect; + +import cc.allio.uno.core.util.Requires; +import lombok.Getter; + +import java.lang.reflect.ParameterizedType; +import java.util.List; +import java.util.stream.Stream; + +/** + * definition how to find {@link ParameterizedType}. and by rawType({@link Class}) and by index and else... + * + * @author j.x + * @date 2024/4/4 17:58 + * @since 1.1.8 + */ +@Getter +public class ParameterizedFinder { + + private final Object byReflectionType; + private final List parameterizedTypes; + + public ParameterizedFinder(Object byReflectionType, List parameterizedTypes) { + Requires.isNotNull(byReflectionType, "original reflection type"); + Requires.isNotNull(parameterizedTypes, "parameterized type"); + this.byReflectionType = byReflectionType; + this.parameterizedTypes = parameterizedTypes; + } + + /** + * find first actual type + * + * @return the actual generic type, maybe null + * @see #findAll() + */ + public Class findFirst() { + Class[] actualTypes = findAll(); + if (actualTypes.length > 0) { + return actualTypes[0]; + } + return null; + } + + /** + * base on {@link Class} raw type get first actual type + * + * @param rawType the raw type, not null. + * @return the actual generic type, maybe null + * @see #find(Class) + */ + public Class findFirst(Class rawType) { + Class[] actualTypes = find(rawType); + if (actualTypes.length > 0) { + return actualTypes[0]; + } + return null; + } + + /** + * base on {@link Class} raw type and actual type index get one actual type + * + * @param rawType the raw type, not nul + * @param index the index + * @return the actual generic type, maybe is null + */ + public Class findIndex(Class rawType, int index) { + Class[] actualTypes = find(rawType); + if (index > actualTypes.length - 1) { + throw new ArrayIndexOutOfBoundsException(String.format("actual types length is %s, but index is %s", actualTypes.length, index)); + } + return actualTypes[index]; + } + + /** + * base on {@link Class} raw type get actual generic type + * + * @param rawType the raw type, not null + * @return not null actual generic type array + */ + public Class[] find(Class rawType) { + Requires.isNotNull(rawType, "rawType"); + return parameterizedTypes + .stream() + .filter(p -> { + if (p.getRawType() instanceof Class rawClass) { + return rawType.isAssignableFrom(rawClass); + } + return false; + }) + .flatMap(p -> Stream.of(p.getActualTypeArguments())) + .filter(t -> Class.class.isAssignableFrom(t.getClass())) + .map(Class.class::cast) + .toArray(Class[]::new); + } + + /** + * find all actual type, whatever raw type + * + * @return actual generic type array + */ + public Class[] findAll() { + return parameterizedTypes + .stream() + .flatMap(p -> Stream.of(p.getActualTypeArguments())) + .filter(t -> Class.class.isAssignableFrom(t.getClass())) + .map(Class.class::cast) + .toArray(Class[]::new); + } +} diff --git a/uno-core/src/main/java/cc/allio/uno/core/reflect/ReflectTools.java b/uno-core/src/main/java/cc/allio/uno/core/reflect/ReflectTools.java index 45c356dc..d21c10bb 100644 --- a/uno-core/src/main/java/cc/allio/uno/core/reflect/ReflectTools.java +++ b/uno-core/src/main/java/cc/allio/uno/core/reflect/ReflectTools.java @@ -2,18 +2,12 @@ import cc.allio.uno.core.concurrent.LockContext; import cc.allio.uno.core.exception.Exceptions; -import cc.allio.uno.core.util.ObjectUtils; -import com.google.common.collect.Lists; import com.google.common.collect.Maps; -import lombok.AllArgsConstructor; -import lombok.Data; import lombok.NonNull; import lombok.extern.slf4j.Slf4j; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.util.Arrays; -import java.util.List; +import java.lang.reflect.Field; +import java.lang.reflect.Method; import java.util.Map; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; @@ -32,6 +26,40 @@ public final class ReflectTools { static final Map[]> OBJ_CLASS_MAPPING_GENERIC_TYPES = Maps.newConcurrentMap(); static final Lock lock = new ReentrantLock(); + static DrawnGeneric> drawnOnClass = new DrawnClass(); + static DrawnGeneric drawnOnMethod = new DrawnMethod(); + static DrawnGeneric drawnOnField = new DrawnField(); + + /** + * drawn generic class(maybe) + * + * @param clazz the class not null + * @return a {@link ParameterizedFinder} instance + */ + public static ParameterizedFinder drawn(Class clazz) { + return drawnOnClass.drawn(clazz); + } + + /** + * drawn generic method(maybe) + * + * @param method the method not null + * @return a {@link ParameterizedFinder} instance + */ + public static ParameterizedFinder drawn(Method method) { + return drawnOnMethod.drawn(method); + } + + /** + * drawn generic {@link Field}(maybe) + * + * @param field the field not nul + * @return a {@link ParameterizedFinder} instance + */ + public static ParameterizedFinder drawn(Field field) { + return drawnOnField.drawn(field); + } + /** * @see #obtainGenericTypes(Class, Class) */ @@ -109,34 +137,12 @@ public static Class[] obtainGenericTypes(Class objClass, Class superCla return LockContext.lock(lock) .lockReturn(() -> { BinaryClassKey binaryClassKey = BinaryClassKey.of(objClass, superClassOrInterface); - return OBJ_CLASS_MAPPING_GENERIC_TYPES.computeIfAbsent(binaryClassKey, key -> { - List genericTypes = findGenericTypes(objClass); - // 默认取第一个匹配的 - Type superType = genericTypes.stream() - .filter(parameterizedType -> { - if (parameterizedType.getRawType() instanceof Class rawClass) { - return superClassOrInterface.isAssignableFrom(rawClass); - } - return false; - }) - .findFirst() - .orElse(null); - if (superType instanceof ParameterizedType parameterizedSuperType) { - Type[] actualTypeArguments = parameterizedSuperType.getActualTypeArguments(); - try { - return Arrays.stream(actualTypeArguments) - // t must be class type - .filter(t -> Class.class.isAssignableFrom(t.getClass())) - .map(Class.class::cast) - .toArray(Class[]::new); - } catch (Throwable ex) { - log.error("obtain generic type by obj class {} from super class {}, happen class cast error", objClass.getName(), superClassOrInterface.getName(), ex); - return new Class[0]; - } - } - return new Class[0]; - }); - + return OBJ_CLASS_MAPPING_GENERIC_TYPES.computeIfAbsent( + binaryClassKey, + key -> { + ParameterizedFinder parameterizedFinder = drawn(objClass); + return parameterizedFinder.find(superClassOrInterface); + }); }) .unchecked(); } @@ -151,42 +157,4 @@ public static Class[] obtainGenericTypes(Class objClass, Class superCla public static int getGenericTypeLength(Class objClass, Class superClassOrInterface) { return obtainGenericTypes(objClass, superClassOrInterface).length; } - - /** - * 从给定的Class对象中获取{@link ParameterizedType}类型,该方法将会递归查找所有范型父类以及范型接口 - * - * @param clazz clazz - * @return list of {@link ParameterizedType} - */ - static List findGenericTypes(Class clazz) { - List types = Lists.newArrayList(); - Type genericSuperclass = clazz.getGenericSuperclass(); - if (genericSuperclass != null) { - if (genericSuperclass instanceof Class superClass && !Object.class.isAssignableFrom(superClass)) { - types.addAll(findGenericTypes(superClass)); - } - if (genericSuperclass instanceof ParameterizedType parameterizedSuperclass) { - types.add(parameterizedSuperclass); - } - } - Type[] genericInterfaces = clazz.getGenericInterfaces(); - if (ObjectUtils.isNotEmpty(genericInterfaces)) { - for (Type genericInterface : genericInterfaces) { - if (genericInterface instanceof Class superInterface) { - types.addAll(findGenericTypes(superInterface)); - } - if (genericInterface instanceof ParameterizedType parameterizedType) { - types.add(parameterizedType); - } - } - } - return types; - } - - @Data - @AllArgsConstructor(staticName = "of") - static class BinaryClassKey { - private final Class cls1; - private final Class cls2; - } } diff --git a/uno-core/src/main/java/cc/allio/uno/core/type/TypeValue.java b/uno-core/src/main/java/cc/allio/uno/core/type/TypeValue.java index 80fea96e..057950bc 100644 --- a/uno-core/src/main/java/cc/allio/uno/core/type/TypeValue.java +++ b/uno-core/src/main/java/cc/allio/uno/core/type/TypeValue.java @@ -1,7 +1,10 @@ package cc.allio.uno.core.type; import cc.allio.uno.core.StringPool; +import cc.allio.uno.core.bean.BeanInfoWrapper; +import cc.allio.uno.core.reflect.ParameterizedFinder; import cc.allio.uno.core.util.ClassUtils; +import cc.allio.uno.core.util.CollectionUtils; import cc.allio.uno.core.util.JsonUtils; import com.google.common.collect.Lists; import com.google.common.collect.Maps; @@ -10,10 +13,12 @@ import lombok.extern.slf4j.Slf4j; import reactor.core.publisher.Flux; +import java.beans.PropertyDescriptor; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.function.Supplier; /** * Type-Value @@ -41,6 +46,8 @@ public class TypeValue { */ private final TypeOperator maybeTypeOperator; + private Supplier parameterizedFinderSupplier; + public TypeValue(Class maybeType, Object value) { this(maybeType, value, TypeOperatorFactory.translator(maybeType)); } @@ -51,6 +58,13 @@ public TypeValue(Class maybeType, Object value, TypeOperator typeOperator) this.maybeTypeOperator = typeOperator; } + public TypeValue(Class maybeType, Object value, TypeOperator typeOperator, Supplier parameterizedFinderSupplier) { + this.maybeType = maybeType; + this.value = value; + this.maybeTypeOperator = typeOperator; + this.parameterizedFinderSupplier = parameterizedFinderSupplier; + } + /** * 以0->0对应关系对应 * @@ -58,14 +72,14 @@ public TypeValue(Class maybeType, Object value, TypeOperator typeOperator) * @param values 具体值 * @return 多数据源 */ - public static Flux of(Class[] types, Object[] values) { + public static Flux of(Class[] types, Object[] values, Supplier parameterizedFinderSupplier) { if (values == null || types.length != values.length) { return Flux.empty(); } return Flux.zip( Flux.fromArray(types), Flux.fromIterable(Lists.newArrayList(values)), - (t, v) -> new TypeValue(t, v, TypeOperatorFactory.translator(t))); + (t, v) -> new TypeValue(t, v, TypeOperatorFactory.translator(t), parameterizedFinderSupplier)); } /** @@ -79,166 +93,230 @@ public static Flux of(Class[] types, Object[] values) { * * @return 值可能正确的类型 */ - public Object tryTransfer() { - Object maybeActual = value; - try { - maybeType.cast(maybeActual); - } catch (ClassCastException e) { - if (log.isTraceEnabled()) { - log.trace("Try cast current value {} for type {} failed", value, maybeType.getName()); - } - if (Types.isArray(maybeType)) { - return arrayTransfer(); - } else if (Types.isSet(maybeType) || Types.isList(maybeType)) { - return collectionTransfer(); - } else if (Types.isMap(maybeType)) { - return mapTransfer(); - } else { - try { - maybeActual = maybeTypeOperator.convert(maybeActual, maybeType); - } catch (NullPointerException | NumberFormatException e2) { - if (log.isTraceEnabled()) { - log.trace("user translator {} getValue actual value {} type failed", maybeTypeOperator.getClass().getName(), value); - } - return value; + public Object tryConvert() { + if (Types.isBean(maybeType)) { + return new BeanConvertor().convert(maybeType, value); + } else if (Types.isArray(maybeType)) { + return new ArrayConvertor().convert(maybeType, value); + } else if (Types.isCollection(maybeType)) { + return new CollectionConvertor(parameterizedFinderSupplier).convert(maybeType, value); + } else if (Types.isMap(maybeType)) { + return new MapConvertor(parameterizedFinderSupplier).convert(maybeType, value); + } else { + return new DirectlyConvertor(maybeTypeOperator).convert(maybeType, value); + } + } + + /** + * type value transfer + */ + interface Convertor { + + /** + * make virtual value to actual value to type + * + * @param maybeType the maybe type + * @param virtualValue the virtual value + * @return actual value + */ + Object convert(Class maybeType, Object virtualValue); + } + + /** + * through the class type cast to virtual value + */ + static class DirectlyConvertor implements Convertor { + private final TypeOperator maybeTypeOperator; + + public DirectlyConvertor(TypeOperator maybeTypeOperator) { + this.maybeTypeOperator = maybeTypeOperator; + } + + @Override + public Object convert(Class maybeType, Object virtualValue) { + try { + return maybeType.cast(virtualValue); + } catch (ClassCastException ex) { + if (log.isTraceEnabled()) { + log.trace("user translator {} getValue actual value {} type failed", maybeTypeOperator.getClass().getName(), virtualValue); + } + if (maybeTypeOperator != null) { + return maybeTypeOperator.convert(virtualValue, maybeType); } } + return null; } - return maybeActual; } /** - * 数组数据转换 - * - * @return array + * convert to java bean. if value is {@link Map} value will be running. otherwise return null */ - private Object[] arrayTransfer() { - Class arrayType = ClassUtils.getArrayClassType(maybeType); - if (arrayType != null) { - // 1.如果值是String类型,则尝试以json,','分隔赋值 - if (Types.isString(value.getClass())) { - try { + static class BeanConvertor implements Convertor { - List arrayValues = JsonUtils.readList(value.toString(), String.class); - Object[] transferValues = new Object[arrayValues.size()]; - for (int i = 0; i < arrayValues.size(); i++) { - transferValues[i] = new TypeValue(arrayType, arrayValues.get(i)).tryTransfer(); + @Override + public Object convert(Class maybeType, Object virtualValue) { + if (virtualValue instanceof Map mapValue) { + Object javaObject = ClassUtils.newInstance(maybeType); + if (javaObject == null) { + return null; + } + BeanInfoWrapper beanInfoWrapper = BeanInfoWrapper.of(maybeType); + if (beanInfoWrapper == null) { + return null; + } + List properties = beanInfoWrapper.properties(); + for (PropertyDescriptor propertyDescriptor : properties) { + String name = propertyDescriptor.getName(); + Object v = mapValue.get(name); + if (v != null) { + Class propertyType = propertyDescriptor.getPropertyType(); + Object actual = new TypeValue(propertyType, v).tryConvert(); + beanInfoWrapper.setForce(javaObject, name, actual); } - return transferValues; - } catch (Throwable ex) { - // 尝试以','分隔 - String[] arrayValues = value.toString().split(StringPool.COMMA); + } + return javaObject; + // same typ + } else if (virtualValue != null && maybeType.isAssignableFrom(virtualValue.getClass())) { + return virtualValue; + } + return null; + } + } + + static class ArrayConvertor implements Convertor { + + @Override + public Object convert(Class maybeType, Object virtualValue) { + Class arrayType = ClassUtils.getArrayClassType(maybeType); + if (arrayType != null) { + // 1.如果值是String类型,则尝试以json,','分隔赋值 + if (Types.isString(virtualValue.getClass())) { + try { + List arrayValues = JsonUtils.readList(virtualValue.toString(), String.class); + Object[] transferValues = new Object[arrayValues.size()]; + for (int i = 0; i < arrayValues.size(); i++) { + transferValues[i] = new TypeValue(arrayType, arrayValues.get(i)).tryConvert(); + } + return transferValues; + } catch (Throwable ex) { + // 尝试以','分隔 + String[] arrayValues = virtualValue.toString().split(StringPool.COMMA); + Object[] transferValues = new Object[arrayValues.length]; + for (int i = 0; i < arrayValues.length; i++) { + transferValues[i] = new TypeValue(arrayType, arrayValues[i]).tryConvert(); + } + return transferValues; + } + } + // 2.如果值array类型,则直接进行转换 + if (Types.isArray(virtualValue.getClass())) { + Object[] arrayValues = (Object[]) virtualValue; Object[] transferValues = new Object[arrayValues.length]; for (int i = 0; i < arrayValues.length; i++) { - transferValues[i] = new TypeValue(arrayType, arrayValues[i]).tryTransfer(); + transferValues[i] = new TypeValue(arrayType, arrayValues[i]).tryConvert(); + } + return transferValues; + } + // 3.如果值是集合类型,进行转换 + if (Types.isList(virtualValue.getClass()) || Types.isSet(virtualValue.getClass())) { + Collection arrayValues = (Collection) virtualValue; + Object[] transferValues = new Object[arrayValues.size()]; + Iterator iterator = arrayValues.iterator(); + int i = 0; + while (iterator.hasNext()) { + transferValues[i] = new TypeValue(arrayType, iterator.next()).tryConvert(); } return transferValues; } } - // 2.如果值array类型,则直接进行转换 - if (Types.isArray(value.getClass())) { - Object[] arrayValues = (Object[]) value; - Object[] transferValues = new Object[arrayValues.length]; - for (int i = 0; i < arrayValues.length; i++) { - transferValues[i] = new TypeValue(arrayType, arrayValues[i]).tryTransfer(); + return new Object[0]; + } + } + + static class CollectionConvertor implements Convertor { + + private final Supplier parameterizedFinderSupplier; + + public CollectionConvertor(Supplier parameterizedFinderSupplier) { + this.parameterizedFinderSupplier = parameterizedFinderSupplier; + } + + @Override + public Object convert(Class maybeType, Object virtualValue) { + Class gType = Object.class; + // 获取集合第一个范型类型 + if (parameterizedFinderSupplier != null) { + ParameterizedFinder parameterizedFinder = parameterizedFinderSupplier.get(); + gType = parameterizedFinder.findFirst(); + } + if (gType == null) { + gType = Object.class; + } + Collection arrayValues = (Collection) virtualValue; + Collection collectionValues = null; + Iterator iterator = arrayValues.iterator(); + if (Types.isList(maybeType)) { + collectionValues = Lists.newArrayListWithCapacity(arrayValues.size()); + while (iterator.hasNext()) { + Object next = iterator.next(); + collectionValues.add(new TypeValue(gType, next).tryConvert()); } - return transferValues; } - // 3.如果值是集合类型,进行转换 - if (Types.isList(value.getClass()) || Types.isSet(value.getClass())) { - Collection arrayValues = (Collection) value; - Object[] transferValues = new Object[arrayValues.size()]; - Iterator iterator = arrayValues.iterator(); - int i = 0; + if (Types.isSet(maybeType)) { + collectionValues = Sets.newHashSetWithExpectedSize(arrayValues.size()); while (iterator.hasNext()) { - transferValues[i] = new TypeValue(arrayType, iterator.next()).tryTransfer(); + Object next = iterator.next(); + collectionValues.add(new TypeValue(gType, next).tryConvert()); } - return transferValues; } + return collectionValues; } - return new Object[0]; } + static class MapConvertor implements Convertor { - /** - * 集合数据转换 - * - * @return collection - */ - private Collection collectionTransfer() { - Class gType; - try { - // 获取集合第一个范型类型 - gType = ClassUtils.getSingleActualGenericType(maybeType); - } catch (ClassNotFoundException e) { - gType = Object.class; + private final Supplier parameterizedFinderSupplier; + + public MapConvertor(Supplier parameterizedFinderSupplier) { + this.parameterizedFinderSupplier = parameterizedFinderSupplier; } - Collection arrayValues = (Collection) value; - Collection collectionValues = null; - Iterator iterator = arrayValues.iterator(); - if (Types.isList(maybeType)) { - collectionValues = Lists.newArrayListWithCapacity(arrayValues.size()); - while (iterator.hasNext()) { - Object next = iterator.next(); - collectionValues.add(new TypeValue(gType, next).tryTransfer()); + + @Override + public Object convert(Class maybeType, Object virtualValue) { + Class keyType = Object.class; + Class valueType = Object.class; + if (parameterizedFinderSupplier != null) { + ParameterizedFinder parameterizedFinder = parameterizedFinderSupplier.get(); + Class[] actualTypes = parameterizedFinder.findAll(); + if (actualTypes.length > 1) { + keyType = actualTypes[0]; + valueType = actualTypes[1]; + } } - } - if (Types.isSet(maybeType)) { - collectionValues = Sets.newHashSetWithExpectedSize(arrayValues.size()); - while (iterator.hasNext()) { - Object next = iterator.next(); - collectionValues.add(new TypeValue(gType, next).tryTransfer()); + Map mapValues = Maps.newHashMap(); + Map transferValue = null; + // 1.判断是否为string数据 + if (Types.isString(virtualValue.getClass())) { + try { + transferValue = JsonUtils.readMap(virtualValue.toString(), Object.class, Object.class); + } catch (Throwable ex) { + // ignore + } } - } - return collectionValues; - } - - /** - * map数据转换 - * - * @return the map - */ - private Map mapTransfer() { - Class keyType = Object.class; - Class valueType = Object.class; - try { - Class[] multiActualGenericType = ClassUtils.getMultiActualGenericType(maybeType); - if (multiActualGenericType.length > 1) { - keyType = multiActualGenericType[0]; - valueType = multiActualGenericType[1]; + // 2.判断是否为map + if (Types.isMap(virtualValue.getClass())) { + transferValue = (Map) virtualValue; } - } catch (ClassNotFoundException e) { - // ignore - } - Map mapValues = Maps.newHashMap(); - // 1.判断是否为string数据 - if (Types.isString(value.getClass())) { - try { - Map jsonValues = JsonUtils.readMap(value.toString(), Object.class, Object.class); - for (Map.Entry jsonEntry : jsonValues.entrySet()) { - Object jKey = jsonEntry.getKey(); - Object jValue = jsonEntry.getValue(); - Object tKey = new TypeValue(keyType, jKey).tryTransfer(); - Object tValue = new TypeValue(valueType, jValue).tryTransfer(); + if (CollectionUtils.isNotEmpty(transferValue)) { + for (Map.Entry oEntry : transferValue.entrySet()) { + Object jKey = oEntry.getKey(); + Object jValue = oEntry.getValue(); + Object tKey = new TypeValue(keyType, jKey).tryConvert(); + Object tValue = new TypeValue(valueType, jValue).tryConvert(); mapValues.put(tKey, tValue); } - return mapValues; - } catch (Throwable ex) { - // ignore - } - } - // 2.判断是否为map - if (Types.isMap(value.getClass())) { - Map oValues = (Map) value; - for (Map.Entry oEntry : oValues.entrySet()) { - Object jKey = oEntry.getKey(); - Object jValue = oEntry.getValue(); - Object tKey = new TypeValue(keyType, jKey).tryTransfer(); - Object tValue = new TypeValue(valueType, jValue).tryTransfer(); - mapValues.put(tKey, tValue); } return mapValues; } - return mapValues; } } diff --git a/uno-core/src/main/java/cc/allio/uno/core/util/Requires.java b/uno-core/src/main/java/cc/allio/uno/core/util/Requires.java index ecd37c5f..c2eb162e 100644 --- a/uno-core/src/main/java/cc/allio/uno/core/util/Requires.java +++ b/uno-core/src/main/java/cc/allio/uno/core/util/Requires.java @@ -10,7 +10,7 @@ * @author jw * @date 2021/12/6 13:57 */ -public class Requires { +public final class Requires { /** * 批量判断请求对象是否为空 @@ -18,8 +18,7 @@ public class Requires { * @param objs 对象数组 */ public static void isNotNulls(Object... objs) { - Arrays.stream(objs) - .forEach(obj -> isNotNull(objs, "")); + Arrays.stream(objs).forEach(obj -> isNotNull(objs, "")); } /** @@ -33,29 +32,5 @@ public static void isNotNull(Object obj, String message) { if (obj == null) { throw new NullPointerException("requires: " + message + " is empty"); } - if (obj instanceof String sv && StringUtils.isEmpty(sv)) { - throw new NullPointerException("requires: " + message + " is empty"); - } - if (obj instanceof Collection coll && CollectionUtils.isEmpty(coll)) { - throw new NullPointerException("requires: " + message + " is empty"); - } - if (obj instanceof Map map && CollectionUtils.isEmpty(map)) { - throw new NullPointerException("requires: " + message + " is empty"); - } - if (obj instanceof Integer i && i == 0) { - throw new NullPointerException("requires: " + message + " is empty"); - } - if (obj instanceof Long l && l == 0L) { - throw new NullPointerException("requires: " + message + " is empty"); - } - if (obj instanceof Double d && d == 0) { - throw new NullPointerException("requires: " + message + " is empty"); - } - if (obj instanceof Float f && f == 0) { - throw new NullPointerException("requires: " + message + " is empty"); - } - if (obj instanceof Boolean bool && Boolean.FALSE.equals(bool)) { - throw new NullPointerException("requires: " + message + " is empty"); - } } } diff --git a/uno-core/src/main/java/cc/allio/uno/core/util/Values.java b/uno-core/src/main/java/cc/allio/uno/core/util/Values.java index fa2e1496..a494bc49 100644 --- a/uno-core/src/main/java/cc/allio/uno/core/util/Values.java +++ b/uno-core/src/main/java/cc/allio/uno/core/util/Values.java @@ -13,13 +13,26 @@ * @date 2024/2/19 17:42 * @since 1.1.7 */ -public class Values { +public final class Values { + + /** + * expand values if value is a array + * + * @param coll the {@link Collection} + * @param the value type + * @return value array + * @see #expand(Object[]) + */ + public static V[] expandCollection(Collection coll) { + return (V[]) expand(coll.toArray()); + } /** * 返回数组 * * @see #streamExpand(Object[]) */ + @SafeVarargs public static V[] expand(V... values) { return (V[]) streamExpand(values).toArray(Object[]::new); } @@ -29,6 +42,7 @@ public static V[] expand(V... values) { * * @see #streamExpand(Object[]) */ + @SafeVarargs public static Collection collectionExpand(V... values) { return streamExpand(values).toList(); } @@ -45,6 +59,7 @@ public static Collection collectionExpand(V... values) { * @param 值类型 * @return value of stream */ + @SafeVarargs public static Stream streamExpand(V... values) { if (values == null) { return Stream.empty(); diff --git a/uno-core/src/test/java/cc/allio/uno/core/bean/BeanInfoWrapperTest.java b/uno-core/src/test/java/cc/allio/uno/core/bean/BeanInfoWrapperTest.java index 07432ed0..42d5d476 100644 --- a/uno-core/src/test/java/cc/allio/uno/core/bean/BeanInfoWrapperTest.java +++ b/uno-core/src/test/java/cc/allio/uno/core/bean/BeanInfoWrapperTest.java @@ -75,9 +75,11 @@ void testSetArray() throws IntrospectionException { void testSetList() throws IntrospectionException { TestComplex testComplex = new TestComplex(); BeanInfoWrapper infoWrapper = new BeanInfoWrapper<>(TestComplex.class); - infoWrapper.set(testComplex, "list", Lists.newArrayList("2", "2")).subscribe(); - + infoWrapper.set(testComplex, "list", Lists.newArrayList(2, "2")).subscribe(); assertEquals(2, testComplex.getList().size()); + + assertEquals("2", testComplex.getList().get(0)); + assertEquals("2", testComplex.getList().get(1)); } @Test diff --git a/uno-core/src/test/java/cc/allio/uno/core/type/TypeValueTest.java b/uno-core/src/test/java/cc/allio/uno/core/type/TypeValueTest.java index d7cc2800..31d9ff88 100644 --- a/uno-core/src/test/java/cc/allio/uno/core/type/TypeValueTest.java +++ b/uno-core/src/test/java/cc/allio/uno/core/type/TypeValueTest.java @@ -2,6 +2,7 @@ import cc.allio.uno.core.BaseTestCase; import com.google.common.collect.Lists; +import lombok.Data; import org.junit.jupiter.api.Test; import java.lang.reflect.Field; @@ -9,50 +10,76 @@ import java.util.Map; import java.util.Set; -public class TypeValueTest extends BaseTestCase { +class TypeValueTest extends BaseTestCase { @Test void testArray() throws NoSuchFieldException { - Field enums = User.class.getDeclaredField("enums"); + Field enums = TypeSet.class.getDeclaredField("enums"); - Object o1 = new TypeValue(enums.getType(), "A").tryTransfer(); + Object o1 = new TypeValue(enums.getType(), "A").tryConvert(); assertTrue(o1.getClass().isArray()); - Object o2 = new TypeValue(enums.getType(), "['A','B']").tryTransfer(); + Object o2 = new TypeValue(enums.getType(), "['A','B']").tryConvert(); assertTrue(o2.getClass().isArray()); - Object o3 = new TypeValue(enums.getType(), Lists.newArrayList(ENUM.A, ENUM.B)).tryTransfer(); + Object o3 = new TypeValue(enums.getType(), Lists.newArrayList(ENUM.A, ENUM.B)).tryConvert(); assertTrue(o3.getClass().isArray()); } @Test void testList() throws NoSuchFieldException { - Field enums = User.class.getDeclaredField("enumsList"); - Object o1 = new TypeValue(enums.getType(), Lists.newArrayList(ENUM.A, ENUM.B)).tryTransfer(); + Field enums = TypeSet.class.getDeclaredField("enumsList"); + Object o1 = new TypeValue(enums.getType(), Lists.newArrayList(ENUM.A, ENUM.B)).tryConvert(); assertTrue(List.class.isAssignableFrom(o1.getClass())); - Field sets = User.class.getDeclaredField("enumsSets"); - Object o2 = new TypeValue(sets.getType(), Lists.newArrayList(ENUM.A, ENUM.B)).tryTransfer(); + Field sets = TypeSet.class.getDeclaredField("enumsSets"); + Object o2 = new TypeValue(sets.getType(), Lists.newArrayList(ENUM.A, ENUM.B)).tryConvert(); assertTrue(Set.class.isAssignableFrom(o2.getClass())); + + Field longList = TypeSet.class.getDeclaredField("longList"); + Object o3 = new TypeValue(longList.getType(), Lists.newArrayList("1", "2")).tryConvert(); + assertTrue(List.class.isAssignableFrom(o3.getClass())); } @Test void testMap() throws NoSuchFieldException { - Field enums = User.class.getDeclaredField("map"); - Object o1 = new TypeValue(enums.getType(), "{'k':'A'}").tryTransfer(); + Field enums = TypeSet.class.getDeclaredField("map"); + Object o1 = new TypeValue(enums.getType(), "{'k':'A'}").tryConvert(); assertTrue(Map.class.isAssignableFrom(o1.getClass())); } - public class User { + @Test + void testCompositeType() { + Object o = new TypeValue(Parent.class, Map.of("children", Map.of("name", "n"))).tryConvert(); + assertNotNull(o); + assertEquals(Parent.class, o.getClass()); + Children children = ((Parent) o).getChildren(); + assertNotNull(children); + + assertEquals("n", children.getName()); + } + + public static class TypeSet { ENUM[] enums; List enumsList; Set enumsSets; Map map; - } + List longList; + } public enum ENUM { A, B } + + @Data + public static class Children { + private String name; + } + + @Data + public static class Parent { + private Children children; + } } diff --git a/uno-core/src/test/java/cc/allio/uno/core/util/ReflectToolTest.java b/uno-core/src/test/java/cc/allio/uno/core/util/ReflectToolTest.java index 618c5c92..b670a4fa 100644 --- a/uno-core/src/test/java/cc/allio/uno/core/util/ReflectToolTest.java +++ b/uno-core/src/test/java/cc/allio/uno/core/util/ReflectToolTest.java @@ -1,10 +1,16 @@ package cc.allio.uno.core.util; import cc.allio.uno.core.BaseTestCase; +import cc.allio.uno.core.reflect.ParameterizedFinder; import cc.allio.uno.core.reflect.ReflectTools; +import lombok.Data; import org.junit.jupiter.api.Test; -public class ReflectToolTest extends BaseTestCase { +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.List; + +class ReflectToolTest extends BaseTestCase { @Test void testGenericType() { @@ -29,6 +35,40 @@ void testGenericType() { assertEquals(String.class, genericType5); } + @Test + void testDrawnMethod() throws NoSuchMethodException { + Method getLongList = GenericMethod.class.getDeclaredMethod("getLongList"); + ParameterizedFinder parameterizedFinder = ReflectTools.drawn(getLongList); + Class first = parameterizedFinder.findFirst(); + assertNotNull(first); + assertEquals(Long.class, first); + + Method setLongList = GenericMethod.class.getDeclaredMethod("setLongList", List.class); + parameterizedFinder = ReflectTools.drawn(setLongList); + first = parameterizedFinder.findFirst(); + assertNotNull(first); + assertEquals(Long.class, first); + + Method getSimply = GenericMethod.class.getDeclaredMethod("getSimply"); + parameterizedFinder = ReflectTools.drawn(getSimply); + first = parameterizedFinder.findFirst(); + assertNull(first); + } + + @Test + void testDrawnField() throws NoSuchFieldException { + Field longList = GenericMethod.class.getDeclaredField("longList"); + ParameterizedFinder parameterizedFinder = ReflectTools.drawn(longList); + Class first = parameterizedFinder.findFirst(); + assertNotNull(first); + assertEquals(Long.class, first); + + Field simply = GenericMethod.class.getDeclaredField("simply"); + parameterizedFinder = ReflectTools.drawn(simply); + first = parameterizedFinder.findFirst(); + assertNull(first); + } + interface A { } @@ -58,4 +98,11 @@ abstract class APenetrateImpl implements APenetrate { class AAPenetrateImpl extends APenetrateImpl { } + + @Data + static class GenericMethod { + private List longList; + + private Long simply; + } } diff --git a/uno-data/uno-data-api/src/main/java/cc/allio/uno/data/orm/dsl/helper/PojoWrapper.java b/uno-data/uno-data-api/src/main/java/cc/allio/uno/data/orm/dsl/helper/PojoWrapper.java index ab083e3e..affb5aa2 100644 --- a/uno-data/uno-data-api/src/main/java/cc/allio/uno/data/orm/dsl/helper/PojoWrapper.java +++ b/uno-data/uno-data-api/src/main/java/cc/allio/uno/data/orm/dsl/helper/PojoWrapper.java @@ -225,6 +225,7 @@ private Table obtainTable() { * */ private List obtainColumnDefs() { + // TODO verify column duplicate return Optional.ofNullable(columnDefs) .orElseGet(() -> Step.>start() @@ -411,6 +412,7 @@ public Mono get(String name, Class fieldType) { .map(javaType -> TypeOperatorFactory.translator(javaType.getJavaType()).convert(value)); }) .cast(fieldType) + .onErrorResume(ex -> Mono.just(value)) .defaultIfEmpty(value); }); } @@ -501,7 +503,6 @@ private static PojoInspect getPojoInspection(Class pojoClass) { return POJO_INSPECTS.computeIfAbsent(pojoClass, k -> Optional.ofNullable(pojoInspectClass).map(ClassUtils::newInstance).orElse(null)); }) .orElse(DEFAULT_POJO_INSPECT); - } /** diff --git a/uno-data/uno-data-api/src/main/java/cc/allio/uno/data/orm/dsl/type/BeanJavaType.java b/uno-data/uno-data-api/src/main/java/cc/allio/uno/data/orm/dsl/type/BeanJavaType.java new file mode 100644 index 00000000..b5d369d5 --- /dev/null +++ b/uno-data/uno-data-api/src/main/java/cc/allio/uno/data/orm/dsl/type/BeanJavaType.java @@ -0,0 +1,26 @@ +package cc.allio.uno.data.orm.dsl.type; + +import lombok.AllArgsConstructor; + +/** + * java bean type + * + * @author j.x + * @date 2024/4/2 18:56 + * @since 1.1.8 + */ +@AllArgsConstructor +public class BeanJavaType extends JavaTypeImpl { + + private final Class beanType; + + @Override + public boolean equalsTo(Class other) { + return beanType.isAssignableFrom(other); + } + + @Override + public Class getJavaType() { + return beanType; + } +} diff --git a/uno-data/uno-data-api/src/main/java/cc/allio/uno/data/orm/dsl/type/TypeRegistry.java b/uno-data/uno-data-api/src/main/java/cc/allio/uno/data/orm/dsl/type/TypeRegistry.java index 628b6243..35d5565b 100644 --- a/uno-data/uno-data-api/src/main/java/cc/allio/uno/data/orm/dsl/type/TypeRegistry.java +++ b/uno-data/uno-data-api/src/main/java/cc/allio/uno/data/orm/dsl/type/TypeRegistry.java @@ -516,11 +516,6 @@ private void initUnknownTypes() { getJdbcType(Types.OTHER), getJavaType(UnknownJavaType.class) ); - // java_object - registerRelation( - getJdbcType(Types.JAVA_OBJECT), - getJavaType(UnknownJavaType.class) - ); // distinct registerRelation( getJdbcType(Types.DISTINCT), @@ -656,10 +651,9 @@ public JavaType findJavaType(Integer jdbcCode) { */ public Collection findJdbcTypeFindJavaType(JavaType javaType) { Collection jdbcCodes = javaTypeMappings.get(javaType); - return - Collections.unmodifiableCollection( - jdbcCodes.stream().map(jdbcTypes::get).collect(Collectors.toList()) - ); + return Collections.unmodifiableCollection( + jdbcCodes.stream().map(jdbcTypes::get).collect(Collectors.toList()) + ); } /** @@ -730,6 +724,10 @@ public JavaType guessJavaType(Class valueType) { if (valueType.isEnum()) { return getJavaType(EnumJavaType.class); } + // 判断是否为bean + if (cc.allio.uno.core.type.Types.isBean(valueType)) { + return new BeanJavaType<>(valueType); + } return getJavaType(UnknownJavaType.class); } diff --git a/uno-data/uno-data-api/src/main/java/cc/allio/uno/data/orm/executor/AbstractCommandExecutor.java b/uno-data/uno-data-api/src/main/java/cc/allio/uno/data/orm/executor/AbstractCommandExecutor.java index 6cf1c040..1eacde07 100644 --- a/uno-data/uno-data-api/src/main/java/cc/allio/uno/data/orm/executor/AbstractCommandExecutor.java +++ b/uno-data/uno-data-api/src/main/java/cc/allio/uno/data/orm/executor/AbstractCommandExecutor.java @@ -2,6 +2,7 @@ import cc.allio.uno.data.orm.dsl.ddl.ShowColumnsOperator; import cc.allio.uno.data.orm.dsl.ddl.ShowTablesOperator; +import cc.allio.uno.data.orm.dsl.dml.UpdateOperator; import cc.allio.uno.data.orm.executor.handler.ListResultSetHandler; import cc.allio.uno.data.orm.executor.handler.ResultSetHandler; import cc.allio.uno.data.orm.executor.interceptor.*; @@ -65,7 +66,14 @@ protected boolean doBool(Operator operator, CommandType commandType, ResultSe case ALERT_TABLE -> manager.getAlter().exec(operator, resultSetHandler); case INSERT -> manager.getInsert().exec(operator, resultSetHandler); case UPDATE -> manager.getUpdate().exec(operator, resultSetHandler); - case DELETE -> manager.getDelete().exec(operator, resultSetHandler); + case DELETE -> { + // maybe execute logic delete + if (operator instanceof UpdateOperator) { + yield manager.getUpdate().exec(operator, resultSetHandler); + } else { + yield manager.getDelete().exec(operator, resultSetHandler); + } + } default -> throw new DSLException(String.format("unknown command type in bool %s, accepted " + "'CREATE_TABLE', 'DELETE_TABLE', 'EXIST_TABLE', 'ALERT_TABLE', 'INSERT', 'UPDATE', 'DELETE'", commandType)); }; diff --git a/uno-data/uno-data-api/src/main/java/cc/allio/uno/data/orm/executor/CommandExecutorFactory.java b/uno-data/uno-data-api/src/main/java/cc/allio/uno/data/orm/executor/CommandExecutorFactory.java index bae7a6bd..eeb02bfd 100644 --- a/uno-data/uno-data-api/src/main/java/cc/allio/uno/data/orm/executor/CommandExecutorFactory.java +++ b/uno-data/uno-data-api/src/main/java/cc/allio/uno/data/orm/executor/CommandExecutorFactory.java @@ -1,5 +1,6 @@ package cc.allio.uno.data.orm.executor; +import cc.allio.uno.data.orm.dsl.type.DBType; import cc.allio.uno.data.orm.executor.options.ExecutorKey; import lombok.extern.slf4j.Slf4j; @@ -62,6 +63,15 @@ public static T getDSLExecutor(String key) return getRegistry().getCommandExecutor(key); } + /** + * base on {@link DBType} get {@link AggregateCommandExecutor} + * + * @see CommandExecutorRegistry#getCommandExecutorByDBTypeFirst(DBType) + */ + public static T getDSLExecutorByDbType(DBType dbType) { + return getRegistry().getCommandExecutorByDBTypeFirst(dbType); + } + /** * 移除Command executor * diff --git a/uno-data/uno-data-api/src/main/java/cc/allio/uno/data/orm/executor/CommandExecutorRegistry.java b/uno-data/uno-data-api/src/main/java/cc/allio/uno/data/orm/executor/CommandExecutorRegistry.java index 9f33d483..82c0b7d6 100644 --- a/uno-data/uno-data-api/src/main/java/cc/allio/uno/data/orm/executor/CommandExecutorRegistry.java +++ b/uno-data/uno-data-api/src/main/java/cc/allio/uno/data/orm/executor/CommandExecutorRegistry.java @@ -1,5 +1,6 @@ package cc.allio.uno.data.orm.executor; +import cc.allio.uno.data.orm.dsl.type.DBType; import cc.allio.uno.data.orm.executor.options.ExecutorKey; import cc.allio.uno.data.orm.executor.options.ExecutorOptions; import jakarta.validation.constraints.NotNull; @@ -59,6 +60,16 @@ public interface CommandExecutorRegistry { */ T getCommandExecutor(String key); + /** + * obtain {@link AggregateCommandExecutor} by {@link DBType}. + *

if a number of {@link AggregateCommandExecutor}, then find first one

+ * + * @param dbType the dbType + * @param the {@link AggregateCommandExecutor} type + * @return {@link AggregateCommandExecutor} instance or null + */ + T getCommandExecutorByDBTypeFirst(DBType dbType); + /** * 基于{@link ExecutorKey}批量移除找到{@link AggregateCommandExecutor}实例 * diff --git a/uno-data/uno-data-api/src/main/java/cc/allio/uno/data/orm/executor/CommandExecutorRegistryImpl.java b/uno-data/uno-data-api/src/main/java/cc/allio/uno/data/orm/executor/CommandExecutorRegistryImpl.java index 7ef179f0..4dda1350 100644 --- a/uno-data/uno-data-api/src/main/java/cc/allio/uno/data/orm/executor/CommandExecutorRegistryImpl.java +++ b/uno-data/uno-data-api/src/main/java/cc/allio/uno/data/orm/executor/CommandExecutorRegistryImpl.java @@ -137,6 +137,24 @@ public T getCommandExecutor(String key) { } } + @Override + public T getCommandExecutorByDBTypeFirst(DBType dbType) { + if (dbType == null) { + return null; + } + Lock readLock = lock.readLock(); + readLock.lock(); + try { + return (T) commandExecutorMap.values() + .stream() + .filter(c -> c.getOptions().getDbType() == dbType) + .findFirst() + .orElse(null); + } finally { + readLock.unlock(); + } + } + @Override public boolean remove(ExecutorKey executorKey) { List executorOptions = matchAll(executorKey); diff --git a/uno-data/uno-data-api/src/main/java/cc/allio/uno/data/orm/executor/DMLCommandExecutor.java b/uno-data/uno-data-api/src/main/java/cc/allio/uno/data/orm/executor/DMLCommandExecutor.java index 3287a606..b69c005f 100644 --- a/uno-data/uno-data-api/src/main/java/cc/allio/uno/data/orm/executor/DMLCommandExecutor.java +++ b/uno-data/uno-data-api/src/main/java/cc/allio/uno/data/orm/executor/DMLCommandExecutor.java @@ -11,6 +11,7 @@ import cc.allio.uno.data.orm.dsl.dml.UpdateOperator; import cc.allio.uno.data.orm.dsl.exception.DSLException; import cc.allio.uno.data.orm.dsl.helper.PojoWrapper; +import cc.allio.uno.data.orm.executor.handler.BoolResultHandler; import cc.allio.uno.data.orm.executor.handler.ListResultSetHandler; import cc.allio.uno.data.orm.executor.handler.ResultSetHandler; import com.google.common.collect.Lists; @@ -770,7 +771,7 @@ default IPage queryPage(IPage page, QueryOperator queryOperator, ListR List r = queryList(queryOperator, resultSetHandler); Long count = queryOne( f -> f.count().from(queryOperator.getTable()), - resultGroup -> resultGroup.getLongValue("count")); + resultGroup -> resultGroup.getLongValue(BoolResultHandler.GUESS_COUNT)); Page rPage = new Page<>(page); rPage.setCurrent(page.getCurrent()); rPage.setSize(page.getSize()); diff --git a/uno-data/uno-data-api/src/main/java/cc/allio/uno/data/orm/executor/ResultRow.java b/uno-data/uno-data-api/src/main/java/cc/allio/uno/data/orm/executor/ResultRow.java index f4148793..17315ff0 100644 --- a/uno-data/uno-data-api/src/main/java/cc/allio/uno/data/orm/executor/ResultRow.java +++ b/uno-data/uno-data-api/src/main/java/cc/allio/uno/data/orm/executor/ResultRow.java @@ -42,4 +42,17 @@ public static ResultRow buildUpdateRow(boolean value) { builder.value(value); return builder.build(); } + + /** + * build the count result value + * + * @param count the count nums value + * @return a {@link ResultRow} instance + */ + public static ResultRow buildCountRow(long count) { + ResultRowBuilder builder = ResultRow.builder(); + builder.column(BoolResultHandler.GUESS_COUNT); + builder.value(count); + return builder.build(); + } } diff --git a/uno-data/uno-data-api/src/main/java/cc/allio/uno/data/orm/executor/handler/BeanResultSetHandler.java b/uno-data/uno-data-api/src/main/java/cc/allio/uno/data/orm/executor/handler/BeanResultSetHandler.java index 555ddd13..f90849b6 100644 --- a/uno-data/uno-data-api/src/main/java/cc/allio/uno/data/orm/executor/handler/BeanResultSetHandler.java +++ b/uno-data/uno-data-api/src/main/java/cc/allio/uno/data/orm/executor/handler/BeanResultSetHandler.java @@ -21,4 +21,9 @@ public BeanResultSetHandler(Class beanClass) { public R apply(ResultGroup resultGroup) { return resultGroup.toEntity(beanClass); } + + @Override + public Class getBeanType() { + return beanClass; + } } diff --git a/uno-data/uno-data-api/src/main/java/cc/allio/uno/data/orm/executor/handler/ListBeanResultSetHandler.java b/uno-data/uno-data-api/src/main/java/cc/allio/uno/data/orm/executor/handler/ListBeanResultSetHandler.java index a8f80c03..b1d8ff3b 100644 --- a/uno-data/uno-data-api/src/main/java/cc/allio/uno/data/orm/executor/handler/ListBeanResultSetHandler.java +++ b/uno-data/uno-data-api/src/main/java/cc/allio/uno/data/orm/executor/handler/ListBeanResultSetHandler.java @@ -30,4 +30,9 @@ public List apply(ResultSet resultSet) { } return r; } + + @Override + public Class getBeanType() { + return handler.getBeanType(); + } } diff --git a/uno-data/uno-data-api/src/main/java/cc/allio/uno/data/orm/executor/internal/ATOInnerCommandExecutor.java b/uno-data/uno-data-api/src/main/java/cc/allio/uno/data/orm/executor/internal/ATOInnerCommandExecutor.java index 7d5ed4e7..48d1ae16 100644 --- a/uno-data/uno-data-api/src/main/java/cc/allio/uno/data/orm/executor/internal/ATOInnerCommandExecutor.java +++ b/uno-data/uno-data-api/src/main/java/cc/allio/uno/data/orm/executor/internal/ATOInnerCommandExecutor.java @@ -1,7 +1,9 @@ package cc.allio.uno.data.orm.executor.internal; import cc.allio.uno.core.reflect.ReflectTools; +import cc.allio.uno.core.util.Values; import cc.allio.uno.data.orm.dsl.ddl.AlterTableOperator; +import org.slf4j.Logger; /** * ATO({@link AlterTableOperator}) inner command type diff --git a/uno-data/uno-data-api/src/main/java/cc/allio/uno/data/orm/executor/internal/InnerCommandExecutor.java b/uno-data/uno-data-api/src/main/java/cc/allio/uno/data/orm/executor/internal/InnerCommandExecutor.java index 93ddf3b6..5305e9a9 100644 --- a/uno-data/uno-data-api/src/main/java/cc/allio/uno/data/orm/executor/internal/InnerCommandExecutor.java +++ b/uno-data/uno-data-api/src/main/java/cc/allio/uno/data/orm/executor/internal/InnerCommandExecutor.java @@ -2,6 +2,11 @@ import cc.allio.uno.data.orm.dsl.Operator; import cc.allio.uno.data.orm.dsl.exception.DSLException; +import com.google.common.collect.Lists; +import org.slf4j.Logger; + +import java.util.List; +import java.util.Map; /** * Definition DSL internal command executor @@ -59,4 +64,23 @@ static > O castTo(Operator original, Class castFor) * @return the operator type */ Class getRealityOperatorType(); + + + /** + * print the inner command msg + * + * @param logger the logger + * @param prints the prints + */ + default void print(Logger logger, Map prints) { + if (logger.isDebugEnabled()) { + StringBuilder printMsg = new StringBuilder(); + printMsg.append("Inner command Executor [{}]"); + for (String printKey : prints.keySet()) { + printMsg.append(" ").append(printKey).append(": ").append("{}"); + } + List printValues = Lists.asList(this.getClass().getSimpleName(), prints.values().toArray()); + logger.debug(printMsg.toString(), printValues.toArray()); + } + } } diff --git a/uno-data/uno-data-api/src/main/java/cc/allio/uno/data/orm/executor/options/ExecutorOptions.java b/uno-data/uno-data-api/src/main/java/cc/allio/uno/data/orm/executor/options/ExecutorOptions.java index 4b42a61f..fe8b8898 100644 --- a/uno-data/uno-data-api/src/main/java/cc/allio/uno/data/orm/executor/options/ExecutorOptions.java +++ b/uno-data/uno-data-api/src/main/java/cc/allio/uno/data/orm/executor/options/ExecutorOptions.java @@ -19,14 +19,14 @@ public interface ExecutorOptions extends ExecutorResultHandlerSet, OptionalContext { String KEY_MARK = "key"; - String DB_TYPE_MARK = "db type"; + String DB_TYPE_MARK = "dbType"; String EXECUTOR_KEY_MARK = "executor"; String OPERATOR_KEY_MARK = "operator"; String USERNAME_MARK = "username"; String PASSWORD_MARK = "password"; String DATABASE_MARK = "database"; String ADDRESS_MARK = "address"; - String SYSTEM_DEFAULT_MARK = "system default"; + String SYSTEM_DEFAULT_MARK = "systemDefault"; /** * 唯一标识 diff --git a/uno-data/uno-data-api/src/main/java/cc/allio/uno/data/orm/executor/options/SPIExecutorOptionsResultHandlerSet.java b/uno-data/uno-data-api/src/main/java/cc/allio/uno/data/orm/executor/options/SPIExecutorOptionsResultHandlerSet.java index 88cb4369..c2f49c04 100644 --- a/uno-data/uno-data-api/src/main/java/cc/allio/uno/data/orm/executor/options/SPIExecutorOptionsResultHandlerSet.java +++ b/uno-data/uno-data-api/src/main/java/cc/allio/uno/data/orm/executor/options/SPIExecutorOptionsResultHandlerSet.java @@ -1,6 +1,5 @@ package cc.allio.uno.data.orm.executor.options; -import cc.allio.uno.core.util.ClassUtils; import cc.allio.uno.data.orm.executor.handler.*; import com.google.common.collect.Maps; @@ -39,7 +38,7 @@ public BoolResultHandler obtainBoolResultHandler() { @Override public BeanResultSetHandler obtainBeanResultSetHandler(Class beanClass) { BeanResultHandlerDelegate beanResultHandler = obtainSPIHandler(BeanResultHandlerDelegate.class, () -> new BeanResultHandlerDelegate(this)); - return beanResultHandler.obtainBeanResultSetHandler(beanClass, BeanResultSetHandler.class, () -> new BeanResultSetHandler<>(beanClass)); + return beanResultHandler.obtainBeanResultSetHandler(beanClass, () -> new BeanResultSetHandler<>(beanClass)); } @Override @@ -67,7 +66,7 @@ public DefaultResultSetHandler obtainDefaultResultSetHandler() { @Override public ListBeanResultSetHandler obtainListBeanResultSetHandler(Class beanClass) { ListBeanResultHandlerDelegate listBeanResultHandlerDelegate = obtainSPIHandler(ListBeanResultHandlerDelegate.class, () -> new ListBeanResultHandlerDelegate(this)); - return listBeanResultHandlerDelegate.obtainListBeanResultSetHandler(beanClass, ListBeanResultSetHandler.class, () -> new ListBeanResultSetHandler<>(beanClass)); + return listBeanResultHandlerDelegate.obtainListBeanResultSetHandler(beanClass, () -> new ListBeanResultSetHandler<>(beanClass)); } @Override @@ -152,27 +151,6 @@ private H obtainSPIHandler(Class handlerClass, Supp }); } - /** - * 基于{@link Class#getConstructors()}创建handler - * - * @param handlerClass handlerClass - * @param defaultHandler defaultHandler - * @param 处理器类型 - * @return Handler 实例 - */ - private H obtainConstructorHandler(Class handlerClass, Supplier defaultHandler, Object[] params) { - return (H) handlerSets.computeIfAbsent( - handlerClass, - k -> { - H handler = ClassUtils.newInstance(handlerClass, params); - if (handler != null) { - handler.setExecutorOptions(this); - return handler; - } - return defaultHandler.get(); - }); - } - /** * 强制添加指定类型的handler * @@ -206,11 +184,11 @@ public BeanResultHandlerDelegate(SPIExecutorOptionsResultHandlerSet executorResu * @param bean handler type * @return BeanResultSetHandler */ - > H obtainBeanResultSetHandler(Class beanClass, Class beanResultHandlerClass, Supplier defaultValue) { + > H obtainBeanResultSetHandler(Class beanClass, Supplier defaultValue) { return (H) beanHandlers.computeIfAbsent( beanClass, k -> { - H handler = executorResultHandlerSet.obtainConstructorHandler(beanResultHandlerClass, defaultValue, new Object[]{beanClass}); + H handler = defaultValue.get(); handler.setExecutorOptions(executorResultHandlerSet); return handler; }); @@ -248,11 +226,11 @@ public ListBeanResultHandlerDelegate(SPIExecutorOptionsResultHandlerSet executor * @param bean handler type * @return BeanResultSetHandler */ - > H obtainListBeanResultSetHandler(Class beanClass, Class beanResultHandlerClass, Supplier defaultValue) { + > H obtainListBeanResultSetHandler(Class beanClass, Supplier defaultValue) { return (H) beanHandlers.computeIfAbsent( beanClass, k -> { - H handler = executorResultHandlerSet.obtainConstructorHandler(beanResultHandlerClass, defaultValue, new Object[]{beanClass}); + H handler = defaultValue.get(); handler.setExecutorOptions(executorResultHandlerSet); return handler; }); diff --git a/uno-data/uno-data-api/src/test/java/cc/allio/uno/data/orm/Role.java b/uno-data/uno-data-api/src/test/java/cc/allio/uno/data/orm/Role.java new file mode 100644 index 00000000..b09cc4f5 --- /dev/null +++ b/uno-data/uno-data-api/src/test/java/cc/allio/uno/data/orm/Role.java @@ -0,0 +1,7 @@ +package cc.allio.uno.data.orm; + +import lombok.Data; + +@Data +public class Role { +} diff --git a/uno-data/uno-data-api/src/test/java/cc/allio/uno/data/orm/executor/handler/ExecutorResultHandlerSetTest.java b/uno-data/uno-data-api/src/test/java/cc/allio/uno/data/orm/executor/handler/ExecutorResultHandlerSetTest.java index dcbd78e7..af90e2bb 100644 --- a/uno-data/uno-data-api/src/test/java/cc/allio/uno/data/orm/executor/handler/ExecutorResultHandlerSetTest.java +++ b/uno-data/uno-data-api/src/test/java/cc/allio/uno/data/orm/executor/handler/ExecutorResultHandlerSetTest.java @@ -1,5 +1,6 @@ package cc.allio.uno.data.orm.executor.handler; +import cc.allio.uno.data.orm.Role; import cc.allio.uno.data.orm.User; import cc.allio.uno.data.orm.dsl.OperatorKey; import cc.allio.uno.data.orm.dsl.type.DBType; @@ -9,7 +10,7 @@ import cc.allio.uno.test.BaseTestCase; import org.junit.jupiter.api.Test; -public class ExecutorResultHandlerSetTest extends BaseTestCase { +class ExecutorResultHandlerSetTest extends BaseTestCase { ExecutorOptions executorOptions = new ExecutorOptionsImpl(DBType.H2, ExecutorKey.DB, OperatorKey.SQL); @@ -43,6 +44,11 @@ void testObtainDefaultResultSetHandler() { void testObtainListBeanResultSetHandler() { ListBeanResultSetHandler userListBeanResultSetHandler = executorOptions.obtainListBeanResultSetHandler(User.class); assertNotNull(userListBeanResultSetHandler); + assertEquals(User.class, userListBeanResultSetHandler.getBeanType()); + + ListBeanResultSetHandler roleListBeanResultSetHandler = executorOptions.obtainListBeanResultSetHandler(Role.class); + assertNotNull(roleListBeanResultSetHandler); + assertEquals(Role.class, roleListBeanResultSetHandler.getBeanType()); } @Test diff --git a/uno-data/uno-data-mongodb/src/main/java/cc/allio/uno/data/orm/dsl/mongodb/MongodbSupport.java b/uno-data/uno-data-mongodb/src/main/java/cc/allio/uno/data/orm/dsl/mongodb/MongodbSupport.java index dbd785ee..f0000948 100644 --- a/uno-data/uno-data-mongodb/src/main/java/cc/allio/uno/data/orm/dsl/mongodb/MongodbSupport.java +++ b/uno-data/uno-data-mongodb/src/main/java/cc/allio/uno/data/orm/dsl/mongodb/MongodbSupport.java @@ -1,9 +1,12 @@ package cc.allio.uno.data.orm.dsl.mongodb; +import cc.allio.uno.core.type.Types; import cc.allio.uno.core.util.JsonUtils; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; import com.google.common.collect.Lists; +import org.bson.BsonArray; +import org.bson.BsonDocument; import org.bson.Document; import java.util.List; @@ -52,4 +55,23 @@ public static String toJson(List docs) { } return items.toPrettyString(); } + + /** + * transfer v to bson value if value is complex type. such as {@link Object}, {@link java.util.Collection}, {@link java.util.Map} + * + * @param v the v + * @return bson document value or raw v + */ + public static Object toBsonValue(Object v) { + if (v == null) { + return null; + } + Class valueType = v.getClass(); + if (Types.isBean(valueType) || Types.isMap(valueType)) { + return BsonDocument.parse(JsonUtils.toJson(v)); + } else if (Types.isCollection(valueType) || Types.isArray(valueType)) { + return BsonArray.parse(JsonUtils.toJson(v)); + } + return v; + } } diff --git a/uno-data/uno-data-mongodb/src/main/java/cc/allio/uno/data/orm/dsl/mongodb/dml/MongodbInsertOperator.java b/uno-data/uno-data-mongodb/src/main/java/cc/allio/uno/data/orm/dsl/mongodb/dml/MongodbInsertOperator.java index 596d2529..eb1b02bf 100644 --- a/uno-data/uno-data-mongodb/src/main/java/cc/allio/uno/data/orm/dsl/mongodb/dml/MongodbInsertOperator.java +++ b/uno-data/uno-data-mongodb/src/main/java/cc/allio/uno/data/orm/dsl/mongodb/dml/MongodbInsertOperator.java @@ -9,6 +9,7 @@ import cc.allio.uno.data.orm.dsl.type.DBType; import com.google.common.collect.Lists; import lombok.Getter; +import org.bson.BsonArray; import org.bson.Document; import java.util.Collection; @@ -110,7 +111,8 @@ public InsertOperator values(List values) { for (int i = 0; i < columns.size(); i++) { DSLName col = columns.get(i); Object v = values.get(i); - document.put(col.format(), v); + Object bsonValue = MongodbSupport.toBsonValue(v); + document.put(col.format(), bsonValue); } this.docs.add(document); return self(); diff --git a/uno-data/uno-data-mongodb/src/main/java/cc/allio/uno/data/orm/dsl/mongodb/dml/MongodbQueryOperator.java b/uno-data/uno-data-mongodb/src/main/java/cc/allio/uno/data/orm/dsl/mongodb/dml/MongodbQueryOperator.java index 5508fca5..e8502411 100644 --- a/uno-data/uno-data-mongodb/src/main/java/cc/allio/uno/data/orm/dsl/mongodb/dml/MongodbQueryOperator.java +++ b/uno-data/uno-data-mongodb/src/main/java/cc/allio/uno/data/orm/dsl/mongodb/dml/MongodbQueryOperator.java @@ -11,6 +11,7 @@ import com.mongodb.client.model.Sorts; import com.mongodb.client.model.Windows; import lombok.Getter; +import lombok.extern.slf4j.Slf4j; import org.bson.conversions.Bson; import java.util.Collection; @@ -23,6 +24,7 @@ * @date 2024/3/14 00:52 * @since 1.1.7 */ +@Slf4j @AutoService(QueryOperator.class) @Operator.Group(OperatorKey.MONGODB_LITERAL) public class MongodbQueryOperator extends MongodbWhereOperatorImpl implements QueryOperator { @@ -36,6 +38,9 @@ public class MongodbQueryOperator extends MongodbWhereOperatorImpl Accumulators.avg(sqlName.format(), null); + case COUNT_FUNCTION -> count = true; } - throw Exceptions.unOperate("aggregate"); + + return self(); } @Override @@ -163,6 +172,9 @@ public QueryOperator limit(Long limit, Long offset) { @Override public QueryOperator groupByOnes(Collection fieldNames) { - throw Exceptions.unOperate("groupByOnes"); + if (log.isDebugEnabled()) { + log.debug("mongodb query operate 'groupByOnes' nothing to do. "); + } + return self(); } } diff --git a/uno-data/uno-data-mongodb/src/main/java/cc/allio/uno/data/orm/dsl/mongodb/dml/MongodbUpdateOperator.java b/uno-data/uno-data-mongodb/src/main/java/cc/allio/uno/data/orm/dsl/mongodb/dml/MongodbUpdateOperator.java index 2f8a2048..bb0d04ff 100644 --- a/uno-data/uno-data-mongodb/src/main/java/cc/allio/uno/data/orm/dsl/mongodb/dml/MongodbUpdateOperator.java +++ b/uno-data/uno-data-mongodb/src/main/java/cc/allio/uno/data/orm/dsl/mongodb/dml/MongodbUpdateOperator.java @@ -2,9 +2,9 @@ import cc.allio.uno.auto.service.AutoService; import cc.allio.uno.core.exception.Exceptions; -import cc.allio.uno.core.type.Types; import cc.allio.uno.data.orm.dsl.*; import cc.allio.uno.data.orm.dsl.dml.UpdateOperator; +import cc.allio.uno.data.orm.dsl.mongodb.MongodbSupport; import cc.allio.uno.data.orm.dsl.type.DBType; import com.google.common.collect.Lists; import com.google.common.collect.Maps; @@ -12,7 +12,6 @@ import lombok.Getter; import org.bson.conversions.Bson; -import java.util.Collection; import java.util.List; import java.util.Map; import java.util.function.Supplier; @@ -120,7 +119,8 @@ public OnceTrigger() { * @param v the v */ public void set(String k, Object v) { - this.updates.put(k, v); + Object bsonValue = MongodbSupport.toBsonValue(v); + this.updates.put(k, bsonValue); } /** @@ -146,13 +146,8 @@ public Bson doIt() { for (Map.Entry entry : updates.entrySet()) { String key = entry.getKey(); Object value = entry.getValue(); - if (value != null && Types.isCollection(value.getClass())) { - Bson field = Updates.addToSet(key, Lists.newArrayList((Collection) value)); - combines.add(field); - } else { - Bson field = Updates.set(key, value); - combines.add(field); - } + Bson field = Updates.set(key, value); + combines.add(field); } return Updates.combine(combines); } diff --git a/uno-data/uno-data-mongodb/src/main/java/cc/allio/uno/data/orm/dsl/mongodb/dml/MongodbWhereOperatorImpl.java b/uno-data/uno-data-mongodb/src/main/java/cc/allio/uno/data/orm/dsl/mongodb/dml/MongodbWhereOperatorImpl.java index 1489da27..6f351240 100644 --- a/uno-data/uno-data-mongodb/src/main/java/cc/allio/uno/data/orm/dsl/mongodb/dml/MongodbWhereOperatorImpl.java +++ b/uno-data/uno-data-mongodb/src/main/java/cc/allio/uno/data/orm/dsl/mongodb/dml/MongodbWhereOperatorImpl.java @@ -1,6 +1,7 @@ package cc.allio.uno.data.orm.dsl.mongodb.dml; import cc.allio.uno.core.type.Types; +import cc.allio.uno.core.util.Values; import cc.allio.uno.data.orm.dsl.DSLName; import cc.allio.uno.data.orm.dsl.WhereOperator; import cc.allio.uno.data.orm.dsl.logical.BiLogical; @@ -99,15 +100,15 @@ public T isNull(DSLName dslName) { @Override public T in(DSLName dslName, V... values) { - Bson expr = Filters.in(dslName.format(), values); + Bson expr = Filters.in(dslName.format(), Values.expand(values)); this.expression.add(expr); this.filter = logical.doAccept(expression); - return null; + return self(); } @Override public T notIn(DSLName dslName, V... values) { - Bson expr = Filters.nin(dslName.format(), values); + Bson expr = Filters.nin(dslName.format(), Values.expand(values)); this.expression.add(expr); this.filter = logical.doAccept(expression); return self(); diff --git a/uno-data/uno-data-mongodb/src/main/java/cc/allio/uno/data/orm/executor/mongodb/internal/MongodbAlterCollectionCommandExecutor.java b/uno-data/uno-data-mongodb/src/main/java/cc/allio/uno/data/orm/executor/mongodb/internal/MongodbAlterCollectionCommandExecutor.java index 5c75245b..96e9e6ec 100644 --- a/uno-data/uno-data-mongodb/src/main/java/cc/allio/uno/data/orm/executor/mongodb/internal/MongodbAlterCollectionCommandExecutor.java +++ b/uno-data/uno-data-mongodb/src/main/java/cc/allio/uno/data/orm/executor/mongodb/internal/MongodbAlterCollectionCommandExecutor.java @@ -16,13 +16,15 @@ import com.mongodb.internal.operation.RenameCollectionOperation; import lombok.extern.slf4j.Slf4j; +import java.util.Map; + /** * mongodb alter collection command executor * * @author j.x * @date 2024/3/15 10:51 - * @since 1.1.7 * @see RenameCollectionOperation + * @since 1.1.7 */ @Slf4j @AutoService(ATOInnerCommandExecutor.class) @@ -50,10 +52,12 @@ public Boolean doExec(MongodbAlterCollectionOperator operator, ResultSetHandler< database.getCollection(from).renameCollection(new MongoNamespace(database.getName(), to)); builder.value(true); } catch (Throwable ex) { - log.error("mongodb alter table has error", ex); + log.error("mongodb alter table has error, the from collection {} alter to collection {}", fromColl.getName().format(), toColl.getName().format(), ex); builder.value(false); } - resultGroup.addRow(builder.build()); + ResultRow resultRow = builder.build(); + resultGroup.addRow(resultRow); + print(log, Map.of("fromColl", fromColl.getName().format(), "toColl", toColl.getName().format(), "result", resultRow.getValue())); return handler.apply(resultGroup); } } diff --git a/uno-data/uno-data-mongodb/src/main/java/cc/allio/uno/data/orm/executor/mongodb/internal/MongodbCreateCollectionCommandExecutor.java b/uno-data/uno-data-mongodb/src/main/java/cc/allio/uno/data/orm/executor/mongodb/internal/MongodbCreateCollectionCommandExecutor.java index 632ac39b..c44030e8 100644 --- a/uno-data/uno-data-mongodb/src/main/java/cc/allio/uno/data/orm/executor/mongodb/internal/MongodbCreateCollectionCommandExecutor.java +++ b/uno-data/uno-data-mongodb/src/main/java/cc/allio/uno/data/orm/executor/mongodb/internal/MongodbCreateCollectionCommandExecutor.java @@ -15,6 +15,8 @@ import com.mongodb.internal.operation.CreateCollectionOperation; import lombok.extern.slf4j.Slf4j; +import java.util.Map; + /** * mongodb create collection command executor * @@ -45,10 +47,12 @@ public Boolean doExec(MongodbCreateCollectionOperator operator, ResultSetHandler database.createCollection(fromColl.getName().format()); builder.value(true); } catch (Throwable ex) { - log.error("mongodb create collection has error", ex); + log.error("mongodb create collection has error, the from collection is {}", fromColl.getName().format(), ex); builder.value(false); } - resultGroup.addRow(builder.build()); + ResultRow resultRow = builder.build(); + resultGroup.addRow(resultRow); + print(log, Map.of("fromColl", fromColl.getName().format(), "result", resultRow.getValue())); return handler.apply(resultGroup); } } diff --git a/uno-data/uno-data-mongodb/src/main/java/cc/allio/uno/data/orm/executor/mongodb/internal/MongodbDeleteCommandExecutor.java b/uno-data/uno-data-mongodb/src/main/java/cc/allio/uno/data/orm/executor/mongodb/internal/MongodbDeleteCommandExecutor.java index cd32d5a7..519e2ee7 100644 --- a/uno-data/uno-data-mongodb/src/main/java/cc/allio/uno/data/orm/executor/mongodb/internal/MongodbDeleteCommandExecutor.java +++ b/uno-data/uno-data-mongodb/src/main/java/cc/allio/uno/data/orm/executor/mongodb/internal/MongodbDeleteCommandExecutor.java @@ -16,6 +16,9 @@ import com.mongodb.client.result.DeleteResult; import lombok.extern.slf4j.Slf4j; import org.bson.Document; +import org.bson.conversions.Bson; + +import java.util.Map; /** * mongodb delete command executor @@ -45,11 +48,13 @@ public Boolean doExec(MongodbDeleteOperator operator, ResultSetHandler ResultRow.ResultRowBuilder builder = ResultRow.builder(); builder.column(BoolResultHandler.GUESS_UPDATE_OR_UPDATE); MongoCollection collection = database.getCollection(fromColl.getName().format()); - DeleteResult deleteResult = collection.deleteMany(operator.getFilter()); + Bson filter = operator.getFilter(); + DeleteResult deleteResult = collection.deleteMany(filter); boolean success = deleteResult.wasAcknowledged() && deleteResult.getDeletedCount() > 0; builder.value(success); - ResultRow row = builder.build(); - resultGroup.addRow(row); + ResultRow resultRow = builder.build(); + print(log, Map.of("fromColl", fromColl.getName().format(), "filter", filter.toBsonDocument().toJson(), "result", resultRow.getValue())); + resultGroup.addRow(resultRow); return handler.apply(resultGroup); } } diff --git a/uno-data/uno-data-mongodb/src/main/java/cc/allio/uno/data/orm/executor/mongodb/internal/MongodbDropCollectionCommandExecutor.java b/uno-data/uno-data-mongodb/src/main/java/cc/allio/uno/data/orm/executor/mongodb/internal/MongodbDropCollectionCommandExecutor.java index b788f602..7282789d 100644 --- a/uno-data/uno-data-mongodb/src/main/java/cc/allio/uno/data/orm/executor/mongodb/internal/MongodbDropCollectionCommandExecutor.java +++ b/uno-data/uno-data-mongodb/src/main/java/cc/allio/uno/data/orm/executor/mongodb/internal/MongodbDropCollectionCommandExecutor.java @@ -17,6 +17,8 @@ import lombok.extern.slf4j.Slf4j; import org.bson.Document; +import java.util.Map; + /** * mongodb drop collection command executor * @@ -51,7 +53,9 @@ public Boolean doExec(MongodbDropCollectionOperator operator, ResultSetHandler builder.value(false); } - ResultRow insertRow = builder.build(); - resultGroup.addRow(insertRow); + ResultRow resultRow = builder.build(); + print(log, Map.of("fromColl", fromColl.getName().format(), "docs", docs, "result", resultRow.getValue())); + resultGroup.addRow(resultRow); return handler.apply(resultGroup); } } diff --git a/uno-data/uno-data-mongodb/src/main/java/cc/allio/uno/data/orm/executor/mongodb/internal/MongodbQueryCommandExecutor.java b/uno-data/uno-data-mongodb/src/main/java/cc/allio/uno/data/orm/executor/mongodb/internal/MongodbQueryCommandExecutor.java index fa4fc493..8c09e16a 100644 --- a/uno-data/uno-data-mongodb/src/main/java/cc/allio/uno/data/orm/executor/mongodb/internal/MongodbQueryCommandExecutor.java +++ b/uno-data/uno-data-mongodb/src/main/java/cc/allio/uno/data/orm/executor/mongodb/internal/MongodbQueryCommandExecutor.java @@ -1,6 +1,7 @@ package cc.allio.uno.data.orm.executor.mongodb.internal; import cc.allio.uno.auto.service.AutoService; +import cc.allio.uno.core.type.Types; import cc.allio.uno.core.util.Requires; import cc.allio.uno.data.orm.dsl.DSLName; import cc.allio.uno.data.orm.dsl.Table; @@ -13,6 +14,7 @@ import cc.allio.uno.data.orm.executor.internal.QOInnerCommandExecutor; import cc.allio.uno.data.orm.executor.options.ExecutorKey; import com.google.common.collect.Lists; +import com.google.common.collect.Maps; import com.mongodb.client.FindIterable; import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoDatabase; @@ -20,6 +22,8 @@ import org.bson.Document; import org.bson.conversions.Bson; +import java.util.Arrays; +import java.util.Collection; import java.util.List; import java.util.Map; @@ -46,28 +50,72 @@ public List doExec(MongodbQueryOperator operator, ListResultSetHandler han // validate Table fromColl = operator.getTable(); Requires.isNotNull(fromColl, "from collection"); - + ResultSet resultSet = new ResultSet(); MongoCollection collection = database.getCollection(fromColl.getName().format()); + + // decide how to use query api Bson filter = operator.getFilter(); - FindIterable documents = collection.find(filter); - List resultGroups = - Lists.newArrayList(documents) - .stream() - .map(document -> { - ResultGroup resultGroup = new ResultGroup(); - for (Map.Entry dEntry : document.entrySet()) { - ResultRow row = ResultRow.builder() - .column(DSLName.of(dEntry.getKey())) - .value(dEntry.getValue()) - .build(); - resultGroup.addRow(row); - } - return resultGroup; - }) - .toList(); - ResultSet resultSet = new ResultSet(); - resultSet.setResultGroups(resultGroups); + // by count + boolean isCount = operator.isCount(); + if (isCount) { + long nums = collection.countDocuments(filter); + ResultRow resultRow = ResultRow.buildCountRow(nums); + ResultGroup resultGroup = new ResultGroup(); + resultGroup.addRow(resultRow); + resultSet.setResultGroups(Lists.newArrayList(resultGroup)); + } else { + // by general query + FindIterable documents = collection.find(filter); + List resultGroups = + Lists.newArrayList(documents) + .stream() + .map(document -> { + ResultGroup resultGroup = new ResultGroup(); + for (Map.Entry dEntry : document.entrySet()) { + ResultRow.ResultRowBuilder rowBuilder = ResultRow.builder(); + String key = dEntry.getKey(); + rowBuilder.column(DSLName.of(key)); + // build filed name - value result row + Object value = dEntry.getValue(); + if (value != null) { + Object javaValue = toJavaValue(value); + rowBuilder.value(javaValue); + } + ResultRow row = rowBuilder.build(); + resultGroup.addRow(row); + } + return resultGroup; + }) + .toList(); + resultSet.setResultGroups(resultGroups); + } + + print(log, Map.of("fromColl", fromColl.getName().format(), "filter", filter)); return handler.apply(resultSet); } + + /** + * change to document value to java value. specific is array and {@link Collection} and {@link Document} + * + * @param v the v, not null + * @return the java value + */ + public Object toJavaValue(Object v) { + if (Types.isArray(v.getClass())) { + return Arrays.stream(((Object[]) v)).map(this::toJavaValue).toArray(Object[]::new); + } else if (v instanceof Collection coll) { + return coll.stream().map(this::toJavaValue).toList(); + } else if (v instanceof Document doc) { + Map docMap = Maps.newHashMap(); + for (Map.Entry docEntry : doc.entrySet()) { + String docKey = docEntry.getKey(); + Object docValue = docEntry.getValue(); + Object javaValue = toJavaValue(docValue); + docMap.put(docKey, javaValue); + } + return docMap; + } + return v; + } } diff --git a/uno-data/uno-data-mongodb/src/main/java/cc/allio/uno/data/orm/executor/mongodb/internal/MongodbShowCollectionCommandExecutor.java b/uno-data/uno-data-mongodb/src/main/java/cc/allio/uno/data/orm/executor/mongodb/internal/MongodbShowCollectionCommandExecutor.java index 90cf65d3..9c196649 100644 --- a/uno-data/uno-data-mongodb/src/main/java/cc/allio/uno/data/orm/executor/mongodb/internal/MongodbShowCollectionCommandExecutor.java +++ b/uno-data/uno-data-mongodb/src/main/java/cc/allio/uno/data/orm/executor/mongodb/internal/MongodbShowCollectionCommandExecutor.java @@ -19,7 +19,9 @@ import lombok.extern.slf4j.Slf4j; import org.bson.Document; +import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; import static cc.allio.uno.data.orm.executor.handler.TableListResultSetHandler.*; @@ -91,7 +93,7 @@ public List doExec(MongodbShowCollectionsOperator operator, ListResultSet return resultGroup; }) .toList(); - + print(log, Collections.emptyMap()); ResultSet resultSet = new ResultSet(); resultSet.setResultGroups(resultGroups); return handler.apply(resultSet); diff --git a/uno-data/uno-data-mongodb/src/main/java/cc/allio/uno/data/orm/executor/mongodb/internal/MongodbUpdateCommandExecutor.java b/uno-data/uno-data-mongodb/src/main/java/cc/allio/uno/data/orm/executor/mongodb/internal/MongodbUpdateCommandExecutor.java index cf24672f..6838053b 100644 --- a/uno-data/uno-data-mongodb/src/main/java/cc/allio/uno/data/orm/executor/mongodb/internal/MongodbUpdateCommandExecutor.java +++ b/uno-data/uno-data-mongodb/src/main/java/cc/allio/uno/data/orm/executor/mongodb/internal/MongodbUpdateCommandExecutor.java @@ -18,6 +18,8 @@ import org.bson.Document; import org.bson.conversions.Bson; +import java.util.Map; + /** * mongodb update command executor * @@ -57,8 +59,9 @@ public Boolean doExec(MongodbUpdateOperator operator, ResultSetHandler log.error("Failed to mongodb update document. the filter bson is {}, update bson is {}", filter, update, ex); builder.value(false); } - ResultRow updateRow = builder.build(); - resultGroup.addRow(updateRow); + ResultRow resultRow = builder.build(); + print(log, Map.of("fromColl", fromColl.getName().format(), "filter", filter, "update", update, "result", resultRow.getValue())); + resultGroup.addRow(resultRow); return handler.apply(resultGroup); } } diff --git a/uno-web/src/main/java/cc/allio/uno/web/source/BaseHttpSource.java b/uno-web/src/main/java/cc/allio/uno/web/source/BaseHttpSource.java index 1c7c2d80..8a7e4ab1 100644 --- a/uno-web/src/main/java/cc/allio/uno/web/source/BaseHttpSource.java +++ b/uno-web/src/main/java/cc/allio/uno/web/source/BaseHttpSource.java @@ -5,7 +5,6 @@ import cc.allio.uno.core.util.StringUtils; import org.springframework.util.ReflectionUtils; import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.util.pattern.PathPatternParser; import java.lang.reflect.Method; import java.util.Map; @@ -19,14 +18,11 @@ public abstract class BaseHttpSource extends JsonSource implements HttpSource { */ protected final String requestMappingUrl; - protected final PathPatternParser parser; - protected BaseHttpSource(String requestMappingUrl) { if (StringUtils.isBlank(requestMappingUrl)) { throw new IllegalArgumentException("requestMappingUrl is empty"); } this.requestMappingUrl = requestMappingUrl; - this.parser = new PathPatternParser(); } public void endpoint(@RequestBody Map value) { diff --git a/uno-web/src/main/java/cc/allio/uno/web/source/HttpSource.java b/uno-web/src/main/java/cc/allio/uno/web/source/HttpSource.java index dc21fd40..4e408abe 100644 --- a/uno-web/src/main/java/cc/allio/uno/web/source/HttpSource.java +++ b/uno-web/src/main/java/cc/allio/uno/web/source/HttpSource.java @@ -4,12 +4,8 @@ import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.context.ApplicationContext; import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition; -import org.springframework.web.servlet.mvc.condition.RequestMethodsRequestCondition; import org.springframework.web.servlet.mvc.method.RequestMappingInfo; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; -import org.springframework.web.util.pattern.PathPattern; -import org.springframework.web.util.pattern.PathPatternParser; import java.lang.reflect.Method; @@ -25,24 +21,20 @@ public interface HttpSource { /** * 注册 * - * @param context spring application context - * @param endpoint 端点方法 - * @param parser 路径解析器 + * @param context spring application context + * @param endpointHandler 端点方法 */ - default void registryEndpoint(ApplicationContext context, Method endpoint, PathPatternParser parser) { + default void registryEndpoint(ApplicationContext context, Method endpointHandler) { RequestMappingHandlerMapping handlerMapping = null; try { - handlerMapping = context.getBean(RequestMappingHandlerMapping.class); + handlerMapping = context.getBean("requestMappingHandlerMapping", RequestMappingHandlerMapping.class); } catch (NoSuchBeanDefinitionException ex) { LoggerFactory.getLogger(getClass()).error("register http source {} failed", getMappingUrl(), ex); } if (handlerMapping != null) { - Method requestMethod = endpoint; - PathPattern pathPattern = parser.parse(getMappingUrl()); - PatternsRequestCondition patternsRequestCondition = new PatternsRequestCondition(pathPattern.getPatternString()); - RequestMethodsRequestCondition requestMethodsRequestCondition = new RequestMethodsRequestCondition(RequestMethod.POST); - RequestMappingInfo mappingInfo = new RequestMappingInfo(patternsRequestCondition, requestMethodsRequestCondition, null, null, null, null, null); - handlerMapping.registerMapping(mappingInfo, this, requestMethod); + String mappingUrl = getMappingUrl(); + RequestMappingInfo mappingInfo = RequestMappingInfo.paths(mappingUrl).methods(RequestMethod.POST).build(); + handlerMapping.registerMapping(mappingInfo, this, endpointHandler); } } diff --git a/uno-web/src/main/java/cc/allio/uno/web/source/ReactiveHttpSource.java b/uno-web/src/main/java/cc/allio/uno/web/source/ReactiveHttpSource.java index 37904379..09280439 100644 --- a/uno-web/src/main/java/cc/allio/uno/web/source/ReactiveHttpSource.java +++ b/uno-web/src/main/java/cc/allio/uno/web/source/ReactiveHttpSource.java @@ -4,11 +4,8 @@ import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.context.ApplicationContext; import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.reactive.result.condition.PatternsRequestCondition; -import org.springframework.web.reactive.result.condition.RequestMethodsRequestCondition; import org.springframework.web.reactive.result.method.RequestMappingInfo; import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerMapping; -import org.springframework.web.util.pattern.PathPattern; import java.lang.reflect.Method; @@ -30,16 +27,13 @@ public ReactiveHttpSource(String requestMappingName) { public void register(ApplicationContext context) { RequestMappingHandlerMapping handlerMapping = null; try { - handlerMapping = context.getBean(RequestMappingHandlerMapping.class); + handlerMapping = context.getBean("requestMappingHandlerMapping", RequestMappingHandlerMapping.class); } catch (NoSuchBeanDefinitionException ex) { log.error("register reactive http source {} failed", requestMappingUrl, ex); } if (handlerMapping != null) { Method requestMethod = getEndpointMethod(); - PathPattern pathPattern = parser.parse(requestMappingUrl); - PatternsRequestCondition patternsRequestCondition = new PatternsRequestCondition(pathPattern); - RequestMethodsRequestCondition requestMethodsRequestCondition = new RequestMethodsRequestCondition(RequestMethod.POST); - RequestMappingInfo mappingInfo = new RequestMappingInfo(patternsRequestCondition, requestMethodsRequestCondition, null, null, null, null, null); + RequestMappingInfo mappingInfo = RequestMappingInfo.paths(requestMappingUrl).methods(RequestMethod.POST).build(); handlerMapping.registerMapping(mappingInfo, this, requestMethod); } } diff --git a/uno-web/src/main/java/cc/allio/uno/web/source/WebHttpSource.java b/uno-web/src/main/java/cc/allio/uno/web/source/WebHttpSource.java index d58cbe25..1fcae86f 100644 --- a/uno-web/src/main/java/cc/allio/uno/web/source/WebHttpSource.java +++ b/uno-web/src/main/java/cc/allio/uno/web/source/WebHttpSource.java @@ -20,6 +20,6 @@ public WebHttpSource(String requestMappingName) { @Override public void register(ApplicationContext context) { - registryEndpoint(context, getEndpointMethod(), parser); + registryEndpoint(context, getEndpointMethod()); } } diff --git a/uno-web/src/main/java/cc/allio/uno/web/source/reactive/WebHttpReactiveSource.java b/uno-web/src/main/java/cc/allio/uno/web/source/reactive/WebHttpReactiveSource.java index 9980559c..fb827de0 100644 --- a/uno-web/src/main/java/cc/allio/uno/web/source/reactive/WebHttpReactiveSource.java +++ b/uno-web/src/main/java/cc/allio/uno/web/source/reactive/WebHttpReactiveSource.java @@ -36,6 +36,6 @@ protected void next(String nextJson) { @Override public void register(ApplicationContext context) { - registryEndpoint(context, getEndpointMethod(), parser); + registryEndpoint(context, getEndpointMethod()); } }