diff --git a/README.md b/README.md index 95e1c07172f6a5386352ab7f462d541ab15781d9..ed00fcfbaa4734c4718b9f815841f795b355e0d6 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ com.gitee.digital-engine dorive-spring-boot-starter - 3.4.2 + 3.4.3.3 ``` @@ -93,7 +93,7 @@ public class Tenant { ```java @RootRepository -@CoatingScan("xxx.xxx.xxx.xxx.xxx.query") +@QueryScan("xxx.xxx.xxx.xxx.xxx.query") public class TenantRepository extends MybatisPlusRepository { } ``` @@ -143,7 +143,7 @@ tenantQuery.setOrder("desc"); tenantQuery.setPage(1); tenantQuery.setLimit(10); -List tenants = tenantRepository.selectByCoating(Selector.ALL, tenantQuery); +List tenants = tenantRepository.selectByQuery(Selector.ALL, tenantQuery); ``` #### 更新数据 diff --git a/dorive-api/pom.xml b/dorive-api/pom.xml index dbc29289910e5e802e58acdb8ea89b676a94689f..ca9f7c8ae970fd51b8f405d975957780d82d2dc4 100644 --- a/dorive-api/pom.xml +++ b/dorive-api/pom.xml @@ -6,7 +6,7 @@ com.gitee.digital-engine dorive - 3.4.3.1 + 3.4.3.3 dorive-api diff --git a/dorive-api/src/main/java/com/gitee/dorive/api/annotation/Field.java b/dorive-api/src/main/java/com/gitee/dorive/api/annotation/Field.java index ff42c494c8ab2504f78497388a1efa33f899e9af..1cf133973d39448fb8541751c98f80e5908d8f39 100644 --- a/dorive-api/src/main/java/com/gitee/dorive/api/annotation/Field.java +++ b/dorive-api/src/main/java/com/gitee/dorive/api/annotation/Field.java @@ -27,6 +27,8 @@ import java.lang.annotation.*; @Target({ElementType.ANNOTATION_TYPE, ElementType.FIELD}) public @interface Field { + boolean isId() default false; + @AliasFor("alias") String value() default ""; diff --git a/dorive-event/src/main/java/com/gitee/dorive/event/annotation/Listener.java b/dorive-api/src/main/java/com/gitee/dorive/api/annotation/Id.java similarity index 78% rename from dorive-event/src/main/java/com/gitee/dorive/event/annotation/Listener.java rename to dorive-api/src/main/java/com/gitee/dorive/api/annotation/Id.java index 7f0e2a1723190caec2373e456080515e7cc6c6a9..169be88eddcf08a02f921ea483ae1fec6f5f9719 100644 --- a/dorive-event/src/main/java/com/gitee/dorive/event/annotation/Listener.java +++ b/dorive-api/src/main/java/com/gitee/dorive/api/annotation/Id.java @@ -15,9 +15,9 @@ * limitations under the License. */ -package com.gitee.dorive.event.annotation; +package com.gitee.dorive.api.annotation; -import org.springframework.stereotype.Component; +import org.springframework.core.annotation.AliasFor; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; @@ -26,11 +26,17 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -@Component +@Field @Inherited @Documented -@Target(ElementType.TYPE) +@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) -public @interface Listener { - Class value(); +public @interface Id { + + @AliasFor(annotation = Field.class) + boolean isId() default true; + + @AliasFor(annotation = Field.class) + String value() default "id"; + } diff --git a/dorive-api/src/main/java/com/gitee/dorive/api/constant/Keys.java b/dorive-api/src/main/java/com/gitee/dorive/api/api/ImplFactory.java similarity index 81% rename from dorive-api/src/main/java/com/gitee/dorive/api/constant/Keys.java rename to dorive-api/src/main/java/com/gitee/dorive/api/api/ImplFactory.java index 75e0b5a498039c6719f78ad1b25624184884ea80..5e6f9f0c54f564e4e841fa349338a9ece77b8d3f 100644 --- a/dorive-api/src/main/java/com/gitee/dorive/api/constant/Keys.java +++ b/dorive-api/src/main/java/com/gitee/dorive/api/api/ImplFactory.java @@ -15,10 +15,10 @@ * limitations under the License. */ -package com.gitee.dorive.api.constant; +package com.gitee.dorive.api.api; + +public interface ImplFactory { + + T getInstance(Class clazz, Object... args); -public interface Keys { - String FIELD_EXECUTOR = "FIELD_EXECUTOR"; - String QUERIER = "QUERIER"; - String TABLE_INFO = "TABLE_INFO"; } diff --git a/dorive-api/src/main/java/com/gitee/dorive/api/constant/Operator.java b/dorive-api/src/main/java/com/gitee/dorive/api/constant/Operator.java index 797b7f1ddb1800aa71a42cc0307b259c16827c1f..d1debe82429bc7ebdc1dfe7a38c45666f58be9a7 100644 --- a/dorive-api/src/main/java/com/gitee/dorive/api/constant/Operator.java +++ b/dorive-api/src/main/java/com/gitee/dorive/api/constant/Operator.java @@ -30,6 +30,8 @@ public interface Operator { String NOT_LIKE = "NOT LIKE"; String IS_NULL = "IS NULL"; String IS_NOT_NULL = "IS NOT NULL"; - String NULL_SWITCH = "NULL_SWITCH"; String MULTI_IN = "MULTI_IN"; + String MULTI_NOT_IN = "MULTI_NOT_IN"; + String AND = "AND"; + String OR = "OR"; } diff --git a/dorive-api/src/main/java/com/gitee/dorive/api/entity/def/FieldDef.java b/dorive-api/src/main/java/com/gitee/dorive/api/entity/def/FieldDef.java index 0bcde9f33652aabbc0580379641fa7e32286c830..b4b90f8ad5584297ccee86af74c670de8a2a8428 100644 --- a/dorive-api/src/main/java/com/gitee/dorive/api/entity/def/FieldDef.java +++ b/dorive-api/src/main/java/com/gitee/dorive/api/entity/def/FieldDef.java @@ -32,6 +32,7 @@ import java.util.Map; @AllArgsConstructor public class FieldDef { + private boolean isId; private String alias; private Class converter; private String mapExp; diff --git a/dorive-api/src/main/java/com/gitee/dorive/api/entity/element/EntityEle.java b/dorive-api/src/main/java/com/gitee/dorive/api/entity/element/EntityEle.java index 3a89c4287ce271908f1d63d08488fe837cb48b47..4a409df9b5e6cdd6caa6e42e3625f3126cbe491b 100644 --- a/dorive-api/src/main/java/com/gitee/dorive/api/entity/element/EntityEle.java +++ b/dorive-api/src/main/java/com/gitee/dorive/api/entity/element/EntityEle.java @@ -26,8 +26,10 @@ import lombok.NoArgsConstructor; import java.lang.reflect.AnnotatedElement; import java.util.ArrayList; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.Set; @Data @NoArgsConstructor @@ -37,8 +39,8 @@ public abstract class EntityEle { private EntityDef entityDef; private boolean aggregated; private List bindingDefs; - private PropProxy pkProxy; - private Map fieldAliasMap; + private PropProxy idProxy; + private Map fieldAliasMapping; public EntityEle(AnnotatedElement element) { this.element = element; @@ -56,17 +58,17 @@ public abstract class EntityEle { } public void initialize() { - if (entityDef != null && pkProxy == null) { + if (entityDef != null && idProxy == null) { doInitialize(); } } public boolean hasField(String field) { - return fieldAliasMap.containsKey(field); + return fieldAliasMapping.containsKey(field); } public String toAlias(String field) { - return fieldAliasMap.getOrDefault(field, field); + return fieldAliasMapping.getOrDefault(field, field); } public List toAliases(List fields) { @@ -81,6 +83,18 @@ public abstract class EntityEle { return fields; } + public Set toAliases(Set fields) { + if (fields != null && !fields.isEmpty()) { + Set aliases = new LinkedHashSet<>(fields.size() * 4 / 3 + 1); + for (String field : fields) { + String alias = toAlias(field); + aliases.add(alias); + } + return aliases; + } + return fields; + } + protected abstract void doInitialize(); public abstract boolean isCollection(); @@ -91,4 +105,6 @@ public abstract class EntityEle { public abstract Map getEntityFieldMap(); + public abstract String getIdName(); + } diff --git a/dorive-api/src/main/java/com/gitee/dorive/api/entity/element/EntityField.java b/dorive-api/src/main/java/com/gitee/dorive/api/entity/element/EntityField.java index 03eca7dc683140ec56359a2541762209f4c9d9f8..772c90ab6f8308d74fd9bf490879c7a734f1a101 100644 --- a/dorive-api/src/main/java/com/gitee/dorive/api/entity/element/EntityField.java +++ b/dorive-api/src/main/java/com/gitee/dorive/api/entity/element/EntityField.java @@ -18,8 +18,8 @@ package com.gitee.dorive.api.entity.element; import cn.hutool.core.util.ReflectUtil; -import com.gitee.dorive.api.entity.def.FieldDef; import com.gitee.dorive.api.entity.def.EntityDef; +import com.gitee.dorive.api.entity.def.FieldDef; import lombok.Data; import lombok.EqualsAndHashCode; @@ -81,8 +81,8 @@ public class EntityField extends EntityEle { protected void doInitialize() { if (entityType != null) { entityType.initialize(); - setPkProxy(entityType.getPkProxy()); - setFieldAliasMap(entityType.getFieldAliasMap()); + setIdProxy(entityType.getIdProxy()); + setFieldAliasMapping(entityType.getFieldAliasMapping()); } } @@ -91,6 +91,11 @@ public class EntityField extends EntityEle { return entityType != null ? entityType.getEntityFieldMap() : null; } + @Override + public String getIdName() { + return entityType != null ? entityType.getIdName() : null; + } + public boolean isSameType(EntityField entityField) { return type == entityField.getType() && genericType == entityField.getGenericType(); } diff --git a/dorive-api/src/main/java/com/gitee/dorive/api/entity/element/EntityType.java b/dorive-api/src/main/java/com/gitee/dorive/api/entity/element/EntityType.java index e1bdeebe473562cba2609c6af4a150c9ce84d316..c004e85f709e6338c675f4d4205e55be05a897e1 100644 --- a/dorive-api/src/main/java/com/gitee/dorive/api/entity/element/EntityType.java +++ b/dorive-api/src/main/java/com/gitee/dorive/api/entity/element/EntityType.java @@ -22,7 +22,7 @@ import cn.hutool.core.lang.Assert; import cn.hutool.core.util.StrUtil; import com.gitee.dorive.api.api.PropProxy; import com.gitee.dorive.api.entity.def.FieldDef; -import com.gitee.dorive.api.exception.CircularDependencyException; +import com.gitee.dorive.api.exception.DefineEntityException; import com.gitee.dorive.api.impl.factory.PropProxyFactory; import com.gitee.dorive.api.util.ReflectUtils; import lombok.Data; @@ -47,6 +47,7 @@ public class EntityType extends EntityEle { private Class type; private String name; + private EntityField idField; private Map entityFieldMap; public static synchronized EntityType getInstance(Class type) { @@ -57,7 +58,7 @@ public class EntityType extends EntityEle { CACHE.put(type, entityType); LOCK.remove(type); } else { - throw new CircularDependencyException("Circular Dependency! type: " + type.getName()); + throw new DefineEntityException("The entity nested itself! type: " + type.getName()); } } return entityType; @@ -67,45 +68,44 @@ public class EntityType extends EntityEle { super(type); this.type = type; this.name = type.getName(); - List fields = ReflectUtils.getAllFields(type); this.entityFieldMap = new LinkedHashMap<>(fields.size() * 4 / 3 + 1); - for (Field field : fields) { if (!Modifier.isStatic(field.getModifiers())) { try { EntityField entityField = new EntityField(field); - entityFieldMap.put(entityField.getName(), entityField); - - } catch (CircularDependencyException e) { + String fieldName = entityField.getName(); + if (idField == null) { + FieldDef fieldDef = entityField.getFieldDef(); + if ("id".equals(fieldName) || (fieldDef != null && fieldDef.isId())) { + idField = entityField; + } + } + entityFieldMap.put(fieldName, entityField); + + } catch (DefineEntityException e) { log.warn(e.getMessage()); } } } - initialize(); } @Override protected void doInitialize() { Class genericType = getGenericType(); - int initialCapacity = entityFieldMap.size() * 4 / 3 + 1; - PropProxy pkProxy = null; - Map propAliasMap = new LinkedHashMap<>(initialCapacity); + Assert.notNull(idField, "The id field cannot be null! type: {}", genericType.getName()); + PropProxy idProxy = PropProxyFactory.newPropProxy(genericType, idField.getName()); + setIdProxy(idProxy); + Map fieldAliasMapping = new LinkedHashMap<>(entityFieldMap.size() * 4 / 3 + 1); for (EntityField entityField : entityFieldMap.values()) { - String name = entityField.getName(); + String fieldName = entityField.getName(); FieldDef fieldDef = entityField.getFieldDef(); - if ("id".equals(name)) { - pkProxy = PropProxyFactory.newPropProxy(genericType, "id"); - } - String alias = fieldDef != null ? fieldDef.getAlias() : StrUtil.toUnderlineCase(name); - propAliasMap.put(name, alias); + String alias = fieldDef != null ? fieldDef.getAlias() : StrUtil.toUnderlineCase(fieldName); + fieldAliasMapping.put(fieldName, alias); } - - Assert.notNull(pkProxy, "The primary key not found! type: {}", genericType.getName()); - setPkProxy(pkProxy); - setFieldAliasMap(propAliasMap); + setFieldAliasMapping(fieldAliasMapping); } @Override @@ -128,4 +128,9 @@ public class EntityType extends EntityEle { return entityFieldMap; } + @Override + public String getIdName() { + return idField.getName(); + } + } diff --git a/dorive-api/src/main/java/com/gitee/dorive/api/exception/CircularDependencyException.java b/dorive-api/src/main/java/com/gitee/dorive/api/exception/DefineEntityException.java similarity index 88% rename from dorive-api/src/main/java/com/gitee/dorive/api/exception/CircularDependencyException.java rename to dorive-api/src/main/java/com/gitee/dorive/api/exception/DefineEntityException.java index 21b0450915639bc649155cc261746017fb32ec83..b865065e2d25384fbb15059424da7a7be3784a1b 100644 --- a/dorive-api/src/main/java/com/gitee/dorive/api/exception/CircularDependencyException.java +++ b/dorive-api/src/main/java/com/gitee/dorive/api/exception/DefineEntityException.java @@ -22,9 +22,9 @@ import lombok.EqualsAndHashCode; @Data @EqualsAndHashCode(callSuper = false) -public class CircularDependencyException extends RuntimeException { +public class DefineEntityException extends RuntimeException { - public CircularDependencyException(String message) { + public DefineEntityException(String message) { super(message); } diff --git a/dorive-core/pom.xml b/dorive-core/pom.xml index 9884ef570aa9c8a020a50471dde812858d0b06e9..23a98eb08aea157168fcfbb8d7eee9a43bc8c09f 100644 --- a/dorive-core/pom.xml +++ b/dorive-core/pom.xml @@ -6,7 +6,7 @@ com.gitee.digital-engine dorive - 3.4.3.1 + 3.4.3.3 dorive-core diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/api/binder/BindingProcessor.java b/dorive-core/src/main/java/com/gitee/dorive/core/api/binder/Processor.java similarity index 96% rename from dorive-core/src/main/java/com/gitee/dorive/core/api/binder/BindingProcessor.java rename to dorive-core/src/main/java/com/gitee/dorive/core/api/binder/Processor.java index 879ab489e3e00e6f5e80972d8804759d053d4b8d..c54ff8168ff05e25e6d40421f91f4dc4a74f9cad 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/api/binder/BindingProcessor.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/api/binder/Processor.java @@ -19,7 +19,7 @@ package com.gitee.dorive.core.api.binder; import com.gitee.dorive.core.api.context.Context; -public interface BindingProcessor { +public interface Processor { Object input(Context context, Object value); diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/api/context/Context.java b/dorive-core/src/main/java/com/gitee/dorive/core/api/context/Context.java index 8957713afa6624b564c9ec58442ab25015716469..ea47340ada39882cb44d2e8ec6f4f62a9953052a 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/api/context/Context.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/api/context/Context.java @@ -19,10 +19,14 @@ package com.gitee.dorive.core.api.context; import java.util.Map; -public interface Context { - - Selector getSelector(); +public interface Context extends Options { Map getAttachments(); + void setAttachment(String name, Object value); + + Object getAttachment(String name); + + void removeAttachment(String name); + } diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/api/context/Node.java b/dorive-core/src/main/java/com/gitee/dorive/core/api/context/Matcher.java similarity index 92% rename from dorive-core/src/main/java/com/gitee/dorive/core/api/context/Node.java rename to dorive-core/src/main/java/com/gitee/dorive/core/api/context/Matcher.java index 21b24d8ba9f5448d144086901de4251bea1c3d8d..d71bd7c43bad0ac5aa74ec8802ca1635697aa4d9 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/api/context/Node.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/api/context/Matcher.java @@ -17,10 +17,8 @@ package com.gitee.dorive.core.api.context; -public interface Node { +public interface Matcher { - boolean isRoot(); - - String getName(); + boolean matches(Context context); } diff --git a/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/entity/Segment.java b/dorive-core/src/main/java/com/gitee/dorive/core/api/context/Options.java similarity index 61% rename from dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/entity/Segment.java rename to dorive-core/src/main/java/com/gitee/dorive/core/api/context/Options.java index db497c4ce3eb740205b14309f5f95a58bbfeb326..545275e78a3c83cff47e2d4428c5acd4c9ddd912 100644 --- a/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/entity/Segment.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/api/context/Options.java @@ -15,29 +15,24 @@ * limitations under the License. */ -package com.gitee.dorive.spring.boot.starter.entity; +package com.gitee.dorive.core.api.context; -import lombok.Data; +import com.gitee.dorive.core.entity.context.EnumOptions; +import com.gitee.dorive.core.entity.option.SelectType; -import java.util.List; +import java.util.Map; -@Data -public class Segment { +public interface Options { - private boolean reachable; - private boolean dirtyQuery; - private List directedSegments; + Options ROOT = new EnumOptions(SelectType.class, SelectType.ROOT); + Options ALL = new EnumOptions(SelectType.class, SelectType.ALL); - public boolean isAvailable() { - return reachable && dirtyQuery; - } + Map, Object> getOptions(); - public String getTableName() { - return null; - } + void setOption(Class type, Object value); - public String getTableAlias() { - return null; - } + Object getOption(Class type); + + void removeOption(Class type); } diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/api/context/Selector.java b/dorive-core/src/main/java/com/gitee/dorive/core/api/context/Selector.java index 96be4e7ece09d7789b6b0ca74b15ba172985ed5f..af7f7df65b03beadb0324d5886a3b52393492f53 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/api/context/Selector.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/api/context/Selector.java @@ -17,20 +17,13 @@ package com.gitee.dorive.core.api.context; -import com.gitee.dorive.core.impl.selector.AllSelector; -import com.gitee.dorive.core.impl.selector.EmptySelector; -import com.gitee.dorive.core.impl.selector.RootSelector; - import java.util.List; +import java.util.Set; -public interface Selector { - - Selector EMPTY = new EmptySelector(); - Selector ROOT = new RootSelector(); - Selector ALL = new AllSelector(); +public interface Selector extends Options { - boolean matches(Context context, Node node); + Set getNames(); - List select(Context context, Node node); + List select(String name); } diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/api/converter/Converter.java b/dorive-core/src/main/java/com/gitee/dorive/core/api/converter/Converter.java new file mode 100644 index 0000000000000000000000000000000000000000..6f85ca0b5132267adc5fdb7cc85471039846d247 --- /dev/null +++ b/dorive-core/src/main/java/com/gitee/dorive/core/api/converter/Converter.java @@ -0,0 +1,26 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.gitee.dorive.core.api.converter; + +public interface Converter { + + Object reconstitute(Object value); + + Object deconstruct(Object value); + +} diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/api/executor/EntityFactory.java b/dorive-core/src/main/java/com/gitee/dorive/core/api/converter/EntityFactory.java similarity index 95% rename from dorive-core/src/main/java/com/gitee/dorive/core/api/executor/EntityFactory.java rename to dorive-core/src/main/java/com/gitee/dorive/core/api/converter/EntityFactory.java index 789cc202d5965b269bbb59ea72f46a4742b203ab..465ed494da5d7a73518e8f51e6c646c8288aac3a 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/api/executor/EntityFactory.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/api/converter/EntityFactory.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package com.gitee.dorive.core.api.executor; +package com.gitee.dorive.core.api.converter; import com.gitee.dorive.core.api.context.Context; diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/impl/selector/AbstractSelector.java b/dorive-core/src/main/java/com/gitee/dorive/core/api/converter/EntityMapper.java similarity index 67% rename from dorive-core/src/main/java/com/gitee/dorive/core/impl/selector/AbstractSelector.java rename to dorive-core/src/main/java/com/gitee/dorive/core/api/converter/EntityMapper.java index 0898c63063df9888a15e2246604124bf8db83ec0..797999132ff9a2eda9e1e27742a8a006fc9af041 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/impl/selector/AbstractSelector.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/api/converter/EntityMapper.java @@ -15,19 +15,22 @@ * limitations under the License. */ -package com.gitee.dorive.core.impl.selector; +package com.gitee.dorive.core.api.converter; -import com.gitee.dorive.core.api.context.Context; -import com.gitee.dorive.core.api.context.Node; -import com.gitee.dorive.core.api.context.Selector; +public interface EntityMapper { -import java.util.List; + String fieldToAlias(String field); -public abstract class AbstractSelector implements Selector { + String aliasToField(String alias); - @Override - public List select(Context context, Node node) { - return null; - } + String fieldToProp(String field); + + boolean hasConverter(); + + Object fieldToAlias(String alias, Object value); + + Object aliasToField(String field, Object value); + + Object fieldToProp(String prop, Object value); } diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/api/executor/FieldConverter.java b/dorive-core/src/main/java/com/gitee/dorive/core/api/executor/EntityJoiner.java similarity index 74% rename from dorive-core/src/main/java/com/gitee/dorive/core/api/executor/FieldConverter.java rename to dorive-core/src/main/java/com/gitee/dorive/core/api/executor/EntityJoiner.java index 36925d5297e74b1edce7ac3d94e730cf4d2a8b57..132a3f48297b40e99e9d38b3a1545d36f262bc68 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/api/executor/FieldConverter.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/api/executor/EntityJoiner.java @@ -18,14 +18,15 @@ package com.gitee.dorive.core.api.executor; import com.gitee.dorive.core.api.context.Context; -import com.gitee.dorive.core.entity.executor.Criterion; +import com.gitee.dorive.core.entity.executor.Example; +import com.gitee.dorive.core.entity.executor.Result; -public interface FieldConverter { +import java.util.List; - Object convert(Context context, Criterion criterion, Object value); +public interface EntityJoiner { - Object reconstitute(String name, Object value); + Example newExample(Context context, List entities); - Object deconstruct(String name, Object value); + void join(Context context, List entities, Result result); } diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/api/format/SqlFormat.java b/dorive-core/src/main/java/com/gitee/dorive/core/api/format/SqlFormat.java new file mode 100644 index 0000000000000000000000000000000000000000..f4deffa8f594b100191bd35e656a7ea6236d567b --- /dev/null +++ b/dorive-core/src/main/java/com/gitee/dorive/core/api/format/SqlFormat.java @@ -0,0 +1,26 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.gitee.dorive.core.api.format; + +public interface SqlFormat { + + Object concatLike(Object value); + + String sqlParam(Object obj); + +} diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/api/repository/ListableRepository.java b/dorive-core/src/main/java/com/gitee/dorive/core/api/repository/ListableRepository.java index 9c770fd7e2347b6f462b685a1812ea157001656c..ac2a661407825f9fb81675ecfd2f5f583a946d64 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/api/repository/ListableRepository.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/api/repository/ListableRepository.java @@ -17,18 +17,18 @@ package com.gitee.dorive.core.api.repository; -import com.gitee.dorive.core.api.context.Context; +import com.gitee.dorive.core.api.context.Options; import java.util.List; public interface ListableRepository extends Repository { - int insertList(Context context, List entities); + int insertList(Options options, List entities); - int updateList(Context context, List entities); + int updateList(Options options, List entities); - int insertOrUpdateList(Context context, List entities); + int insertOrUpdateList(Options options, List entities); - int deleteList(Context context, List entities); + int deleteList(Options options, List entities); } diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/api/repository/Repository.java b/dorive-core/src/main/java/com/gitee/dorive/core/api/repository/Repository.java index 711fa84d81b44937fe258045bcc59026b7813825..c6681e9861724cbc2d5541e30eaa91d59860b66d 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/api/repository/Repository.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/api/repository/Repository.java @@ -17,7 +17,7 @@ package com.gitee.dorive.core.api.repository; -import com.gitee.dorive.core.api.context.Context; +import com.gitee.dorive.core.api.context.Options; import com.gitee.dorive.core.entity.executor.Example; import com.gitee.dorive.core.entity.executor.Page; @@ -34,102 +34,112 @@ public interface Repository { /** * 根据主键,查询实体 * - * @param context 上下文 + * @param options 可选项 * @param primaryKey 主键 * @return 实体 */ - E selectByPrimaryKey(Context context, PK primaryKey); + E selectByPrimaryKey(Options options, PK primaryKey); /** * 根据条件,查询实体 * - * @param context 上下文 + * @param options 可选项 * @param example 条件 * @return 实体 */ - List selectByExample(Context context, Example example); + List selectByExample(Options options, Example example); + + /** + * 根据条件,查询实体 + * 如果存在多条记录,取第一条 + * + * @param options 可选项 + * @param example 条件 + * @return 实体 + */ + E selectOneByExample(Options options, Example example); /** * 根据条件,查询分页 * - * @param context 上下文 + * @param options 可选项 * @param example 条件 * @return 分页 */ - Page selectPageByExample(Context context, Example example); + Page selectPageByExample(Options options, Example example); /** * 根据条件,查询计数 * - * @param context 上下文 + * @param options 可选项 * @param example 条件 * @return 计数 */ - long selectCount(Context context, Example example); + long selectCountByExample(Options options, Example example); /** * 插入一个实体 * - * @param context 上下文 + * @param options 可选项 * @param entity 实体 * @return 操作数 */ - int insert(Context context, E entity); + int insert(Options options, E entity); /** * 根据实体的主键,修改一个实体 * - * @param context 上下文 + * @param options 可选项 * @param entity 实体 * @return 操作数 */ - int update(Context context, E entity); + int update(Options options, E entity); /** * 根据实体和条件,修改聚合内的所有实体 * - * @param context 上下文 + * @param options 可选项 * @param entity 实体 * @param example 条件 * @return 操作数 */ - int updateByExample(Context context, Object entity, Example example); + int updateByExample(Options options, Object entity, Example example); /** * 根据实体的主键,插入或者修改一个实体。 * 主键为空则插入,主键非空则修改。 * - * @param context 上下文 + * @param options 可选项 * @param entity 实体 * @return 操作数 */ - int insertOrUpdate(Context context, E entity); + int insertOrUpdate(Options options, E entity); /** * 根据实体的主键,删除一个实体 * - * @param context 上下文 + * @param options 可选项 * @param entity 实体 * @return 操作数 */ - int delete(Context context, E entity); + int delete(Options options, E entity); /** * 根据主键,删除一个实体 * - * @param context 上下文 + * @param options 可选项 * @param primaryKey 主键 * @return 操作数 */ - int deleteByPrimaryKey(Context context, PK primaryKey); + int deleteByPrimaryKey(Options options, PK primaryKey); /** * 根据条件,删除聚合内的所有实体 * - * @param context 上下文 + * @param options 可选项 * @param example 条件 * @return 操作数 */ - int deleteByExample(Context context, Example example); + int deleteByExample(Options options, Example example); } diff --git a/dorive-coating/src/main/java/com/gitee/dorive/coating/entity/CoatingCriteria.java b/dorive-core/src/main/java/com/gitee/dorive/core/entity/common/EntityStoreInfo.java similarity index 69% rename from dorive-coating/src/main/java/com/gitee/dorive/coating/entity/CoatingCriteria.java rename to dorive-core/src/main/java/com/gitee/dorive/core/entity/common/EntityStoreInfo.java index 7d573b18caa53100ef8a41eb3aa7ac02c9ce3274..62c7b7cf0d247853e07fa8723011b7ca4ae75b50 100644 --- a/dorive-coating/src/main/java/com/gitee/dorive/coating/entity/CoatingCriteria.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/entity/common/EntityStoreInfo.java @@ -15,21 +15,23 @@ * limitations under the License. */ -package com.gitee.dorive.coating.entity; +package com.gitee.dorive.core.entity.common; -import com.gitee.dorive.core.entity.executor.Criterion; -import com.gitee.dorive.core.entity.executor.OrderBy; -import com.gitee.dorive.core.entity.executor.Page; import lombok.AllArgsConstructor; import lombok.Data; -import java.util.List; import java.util.Map; @Data @AllArgsConstructor -public class CoatingCriteria { - private Map> criteriaMap; - private OrderBy orderBy; - private Page page; +public class EntityStoreInfo { + private Class mapperClass; + private Object mapper; + private Class pojoClass; + private String tableName; + private String idProperty; + private String idColumn; + private Map propAliasMappingWithoutPk; + private Map propAliasMapping; + private String selectColumns; } diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/entity/context/AbstractContext.java b/dorive-core/src/main/java/com/gitee/dorive/core/entity/context/AbstractContext.java index 4db5f3978f1243260ff9fb15ded8fefd5b681d94..d011dcab34e5fe0ba813c4e079f4d2d1eee15cfd 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/entity/context/AbstractContext.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/entity/context/AbstractContext.java @@ -18,38 +18,59 @@ package com.gitee.dorive.core.entity.context; import com.gitee.dorive.core.api.context.Context; -import com.gitee.dorive.core.api.context.Selector; -import lombok.Data; +import com.gitee.dorive.core.api.context.Options; +import lombok.Getter; import lombok.NoArgsConstructor; +import lombok.Setter; import java.util.LinkedHashMap; import java.util.Map; -@Data +@Getter +@Setter @NoArgsConstructor public abstract class AbstractContext implements Context { - private Selector selector = Selector.EMPTY; - private Map attachments = new LinkedHashMap<>(8); + protected Map, Object> options = new LinkedHashMap<>(4); + protected Map attachments = new LinkedHashMap<>(8); - public AbstractContext(Selector selector) { - this.selector = selector; + public AbstractContext(Options options) { + this.options.putAll(options.getOptions()); } - public Object put(String key, Object value) { - return attachments.put(key, value); + public AbstractContext(Context anotherContext) { + this.options.putAll(anotherContext.getOptions()); + this.attachments.putAll(anotherContext.getAttachments()); } - public boolean containsKey(String key) { - return attachments.containsKey(key); + @Override + public void setOption(Class type, Object value) { + options.put(type, value); } - public Object get(String key) { - return attachments.get(key); + @Override + public Object getOption(Class type) { + return options.get(type); } - public Object remove(String key) { - return attachments.remove(key); + @Override + public void removeOption(Class type) { + options.remove(type); + } + + @Override + public void setAttachment(String name, Object value) { + attachments.put(name, value); + } + + @Override + public Object getAttachment(String name) { + return attachments.get(name); + } + + @Override + public void removeAttachment(String name) { + attachments.remove(name); } } diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/entity/context/BoundedContext.java b/dorive-core/src/main/java/com/gitee/dorive/core/entity/context/BoundedContext.java index d33be1af006f09e777c2039befe735e22890b6d2..9174f4454e6a43c4cf5a68006bdd7e11e221d77c 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/entity/context/BoundedContext.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/entity/context/BoundedContext.java @@ -17,18 +17,19 @@ package com.gitee.dorive.core.entity.context; -import com.gitee.dorive.core.api.context.Selector; -import lombok.Data; -import lombok.EqualsAndHashCode; +import com.gitee.dorive.core.api.context.Context; +import com.gitee.dorive.core.api.context.Options; import lombok.NoArgsConstructor; -@Data @NoArgsConstructor -@EqualsAndHashCode(callSuper = false) public class BoundedContext extends AbstractContext { - public BoundedContext(Selector selector) { - super(selector); + public BoundedContext(Options options) { + super(options); + } + + public BoundedContext(Context anotherContext) { + super(anotherContext); } } diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/entity/executor/MultiResult.java b/dorive-core/src/main/java/com/gitee/dorive/core/entity/context/EnumOptions.java similarity index 52% rename from dorive-core/src/main/java/com/gitee/dorive/core/entity/executor/MultiResult.java rename to dorive-core/src/main/java/com/gitee/dorive/core/entity/context/EnumOptions.java index ca49bdecb4954ccbccd81ee5ccf5df310fab52fe..205c50012ea2aea1dba18cb6d1880b862b6593d3 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/entity/executor/MultiResult.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/entity/context/EnumOptions.java @@ -15,27 +15,39 @@ * limitations under the License. */ -package com.gitee.dorive.core.entity.executor; +package com.gitee.dorive.core.entity.context; -import lombok.Data; -import lombok.EqualsAndHashCode; +import com.gitee.dorive.core.api.context.Options; -import java.util.List; +import java.util.Collections; import java.util.Map; -@Data -@EqualsAndHashCode(callSuper = false) -public class MultiResult extends Result { +public class EnumOptions implements Options { - private List> resultMaps; + private final Map, Object> options; - public MultiResult(Page page, List> resultMaps) { - setPage(page); - this.resultMaps = resultMaps; + public EnumOptions(Class type, Object value) { + this.options = Collections.singletonMap(type, value); } - public MultiResult(List> resultMaps) { - this.resultMaps = resultMaps; + @Override + public Map, Object> getOptions() { + return options; + } + + @Override + public void setOption(Class type, Object value) { + throw new UnsupportedOperationException(); + } + + @Override + public Object getOption(Class type) { + return options.get(type); + } + + @Override + public void removeOption(Class type) { + throw new UnsupportedOperationException(); } } diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/entity/context/InnerContext.java b/dorive-core/src/main/java/com/gitee/dorive/core/entity/context/InnerContext.java index 004c82ec6969042aea6ce2e5d683dd721ae0ffca..b70e6f8a96899575d669e1481836631afe8866ce 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/entity/context/InnerContext.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/entity/context/InnerContext.java @@ -17,18 +17,19 @@ package com.gitee.dorive.core.entity.context; -import com.gitee.dorive.core.api.context.Selector; -import lombok.Data; -import lombok.EqualsAndHashCode; +import com.gitee.dorive.core.api.context.Context; +import com.gitee.dorive.core.api.context.Options; import lombok.NoArgsConstructor; -@Data @NoArgsConstructor -@EqualsAndHashCode(callSuper = false) public class InnerContext extends AbstractContext { - public InnerContext(Selector selector) { - super(selector); + public InnerContext(Options options) { + super(options); + } + + public InnerContext(Context anotherContext) { + super(anotherContext); } } diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/entity/executor/Criterion.java b/dorive-core/src/main/java/com/gitee/dorive/core/entity/executor/Criterion.java index d856c8b995891686922f790a1d344fe587a010fa..ff13143d8d58dc084b75110fe408085a66e4853d 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/entity/executor/Criterion.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/entity/executor/Criterion.java @@ -17,6 +17,7 @@ package com.gitee.dorive.core.entity.executor; +import com.gitee.dorive.core.util.CriterionUtils; import lombok.AllArgsConstructor; import lombok.Data; @@ -33,8 +34,9 @@ public class Criterion { this.operator = operator; } - public Criterion tryClone() { - return new Criterion(property, operator, value); + @Override + public String toString() { + return CriterionUtils.toString(this); } } diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/entity/executor/Example.java b/dorive-core/src/main/java/com/gitee/dorive/core/entity/executor/Example.java index 8b9d547b315dcf32981a508e2299c9ece64ebd71..3cfb3287f513c2b9730f907b35735d59c5ecebff 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/entity/executor/Example.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/entity/executor/Example.java @@ -26,13 +26,14 @@ import lombok.NoArgsConstructor; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.function.Consumer; @Data @NoArgsConstructor public class Example { private List selectProps; - private List extraProps; + private String selectSuffix; private List criteria = new ArrayList<>(4); private OrderBy orderBy; private Page page; @@ -41,24 +42,12 @@ public class Example { this.criteria = criteria; } - public void select(List properties) { - selectProps = properties; + public void select(List fields) { + selectProps = fields; } - public void select(String... properties) { - select(StringUtils.toList(properties)); - } - - public void selectExtra(List properties) { - if (extraProps == null) { - extraProps = properties; - } else { - extraProps.addAll(properties); - } - } - - public void selectExtra(String... properties) { - selectExtra(StringUtils.toList(properties)); + public void select(String... fields) { + select(StringUtils.toList(fields)); } public boolean isEmpty() { @@ -69,73 +58,87 @@ public class Example { return !criteria.isEmpty(); } - public Example eq(String property, Object value) { - criteria.add(new Criterion(property, Operator.EQ, value)); + public Example eq(String field, Object value) { + criteria.add(new Criterion(field, Operator.EQ, value)); + return this; + } + + public Example ne(String field, Object value) { + criteria.add(new Criterion(field, Operator.NE, value)); + return this; + } + + public Example gt(String field, Object value) { + criteria.add(new Criterion(field, Operator.GT, value)); return this; } - public Example ne(String property, Object value) { - criteria.add(new Criterion(property, Operator.NE, value)); + public Example ge(String field, Object value) { + criteria.add(new Criterion(field, Operator.GE, value)); return this; } - public Example gt(String property, Object value) { - criteria.add(new Criterion(property, Operator.GT, value)); + public Example lt(String field, Object value) { + criteria.add(new Criterion(field, Operator.LT, value)); return this; } - public Example ge(String property, Object value) { - criteria.add(new Criterion(property, Operator.GE, value)); + public Example le(String field, Object value) { + criteria.add(new Criterion(field, Operator.LE, value)); return this; } - public Example lt(String property, Object value) { - criteria.add(new Criterion(property, Operator.LT, value)); + public Example in(String field, Object value) { + criteria.add(new Criterion(field, Operator.IN, value)); return this; } - public Example le(String property, Object value) { - criteria.add(new Criterion(property, Operator.LE, value)); + public Example notIn(String field, Object value) { + criteria.add(new Criterion(field, Operator.NOT_IN, value)); return this; } - public Example in(String property, Object value) { - criteria.add(new Criterion(property, Operator.IN, value)); + public Example like(String field, Object value) { + criteria.add(new Criterion(field, Operator.LIKE, value)); return this; } - public Example notIn(String property, Object value) { - criteria.add(new Criterion(property, Operator.NOT_IN, value)); + public Example notLike(String field, Object value) { + criteria.add(new Criterion(field, Operator.NOT_LIKE, value)); return this; } - public Example like(String property, Object value) { - criteria.add(new Criterion(property, Operator.LIKE, value)); + public Example isNull(String field) { + criteria.add(new Criterion(field, Operator.IS_NULL)); return this; } - public Example notLike(String property, Object value) { - criteria.add(new Criterion(property, Operator.NOT_LIKE, value)); + public Example isNotNull(String field) { + criteria.add(new Criterion(field, Operator.IS_NOT_NULL)); return this; } - public Example isNull(String property) { - criteria.add(new Criterion(property, Operator.IS_NULL)); + public Example and(Consumer consumer) { + Example example = new InnerExample(); + consumer.accept(example); + criteria.add(new Criterion("@Lambda", Operator.AND, example)); return this; } - public Example isNotNull(String property) { - criteria.add(new Criterion(property, Operator.IS_NOT_NULL)); + public Example or(Consumer consumer) { + Example example = new InnerExample(); + consumer.accept(example); + criteria.add(new Criterion("@Lambda", Operator.OR, example)); return this; } - public Example orderByAsc(String... properties) { - orderBy = new OrderBy(Arrays.asList(properties), Order.ASC); + public Example orderByAsc(String... fields) { + orderBy = new OrderBy(Arrays.asList(fields), Order.ASC); return this; } - public Example orderByDesc(String... properties) { - orderBy = new OrderBy(Arrays.asList(properties), Order.DESC); + public Example orderByDesc(String... fields) { + orderBy = new OrderBy(Arrays.asList(fields), Order.DESC); return this; } diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/entity/executor/OrderBy.java b/dorive-core/src/main/java/com/gitee/dorive/core/entity/executor/OrderBy.java index 76cd1d6fa7e95d1eaf2b2c33611a3153db9d643b..9c874e6dfea13198bf1b81864b74873a2813bedc 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/entity/executor/OrderBy.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/entity/executor/OrderBy.java @@ -21,7 +21,6 @@ import cn.hutool.core.util.StrUtil; import lombok.AllArgsConstructor; import lombok.Data; -import java.util.ArrayList; import java.util.List; @Data @@ -31,10 +30,6 @@ public class OrderBy { private List properties; private String order; - public OrderBy tryClone() { - return new OrderBy(new ArrayList<>(properties), order); - } - @Override public String toString() { return "ORDER BY " + StrUtil.join(",", properties) + " " + order.toUpperCase(); diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/entity/executor/Page.java b/dorive-core/src/main/java/com/gitee/dorive/core/entity/executor/Page.java index 41dba0e93e0f80e0c4d302f7ff01a83dfe1bc32c..e368926cb90906260f26a3128ff4e00dc1fab4ca 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/entity/executor/Page.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/entity/executor/Page.java @@ -21,7 +21,6 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; -import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -40,10 +39,6 @@ public class Page { this.size = size; } - public Page tryClone() { - return new Page<>(total, current, size, new ArrayList<>(records)); - } - @Override public String toString() { return "LIMIT " + (current - 1) * size + "," + size; diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/entity/executor/Result.java b/dorive-core/src/main/java/com/gitee/dorive/core/entity/executor/Result.java index 62afcb67e13b5f08f1d61a0a7116f563d4e3c05d..c92bbb2db43c0f12218ae68f52d4d9d926bb131b 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/entity/executor/Result.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/entity/executor/Result.java @@ -22,16 +22,24 @@ import lombok.NoArgsConstructor; import java.util.Collections; import java.util.List; +import java.util.Map; @Data @NoArgsConstructor public class Result { private Page page; + private List> recordMaps = Collections.emptyList(); private List records = Collections.emptyList(); private E record; private long count = 0L; + public Result(Page page, List> recordMaps) { + this.page = page; + this.recordMaps = recordMaps; + this.count = this.recordMaps.size(); + } + public Result(Page page) { this.page = page; this.records = page.getRecords(); diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/entity/executor/UnionExample.java b/dorive-core/src/main/java/com/gitee/dorive/core/entity/executor/UnionExample.java index 33487582bdc597eb6cec51ad7ea8234dd799cf95..dadc490c2bfcde7a48b0d45bc30857a2ce6ebbf6 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/entity/executor/UnionExample.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/entity/executor/UnionExample.java @@ -32,17 +32,13 @@ public class UnionExample extends Example { private List examples = new ArrayList<>(); @Override - public boolean isNotEmpty() { - return !examples.isEmpty(); + public boolean isEmpty() { + return examples.isEmpty(); } @Override - public void select(List properties) { - if (examples != null && !examples.isEmpty()) { - for (Example example : examples) { - example.select(properties); - } - } + public boolean isNotEmpty() { + return !examples.isEmpty(); } public void addExample(Example example) { diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/entity/operation/Condition.java b/dorive-core/src/main/java/com/gitee/dorive/core/entity/operation/Condition.java index 5a3db03df153cd8d47b004bf47041607159ed5b7..d16fd4b40672ddf9d6723f328cb2acdf0d8024fb 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/entity/operation/Condition.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/entity/operation/Condition.java @@ -28,8 +28,8 @@ public class Condition extends Operation { private Object primaryKey; private Example example; - public Condition(int type, Object entity) { - super(type, entity); + public Condition(Object entity) { + super(entity); } } diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/entity/operation/Delete.java b/dorive-core/src/main/java/com/gitee/dorive/core/entity/operation/Delete.java index c9f7f3e92d359e9141faa515f3d5d10799ab4a1b..5731ab569591f19e5c168574673f968b66195501 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/entity/operation/Delete.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/entity/operation/Delete.java @@ -17,7 +17,6 @@ package com.gitee.dorive.core.entity.operation; -import com.gitee.dorive.api.constant.OperationType; import lombok.Getter; import lombok.Setter; @@ -25,12 +24,8 @@ import lombok.Setter; @Setter public class Delete extends Condition { - public Delete(int type, Object entity) { - super(type, entity); - } - public Delete(Object entity) { - super(OperationType.DELETE, entity); + super(entity); } } diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/entity/operation/Insert.java b/dorive-core/src/main/java/com/gitee/dorive/core/entity/operation/Insert.java index 1a0ad3faafec1b1de7612b6729cc2d6b74e9299e..60a5e0c17a8d304c4f98c4f62fa58b853e56be18 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/entity/operation/Insert.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/entity/operation/Insert.java @@ -17,7 +17,6 @@ package com.gitee.dorive.core.entity.operation; -import com.gitee.dorive.api.constant.OperationType; import lombok.Getter; import lombok.Setter; @@ -25,12 +24,8 @@ import lombok.Setter; @Setter public class Insert extends Operation { - public Insert(int type, Object entity) { - super(type, entity); - } - public Insert(Object entity) { - super(OperationType.INSERT, entity); + super(entity); } } diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/entity/operation/InsertOrUpdate.java b/dorive-core/src/main/java/com/gitee/dorive/core/entity/operation/InsertOrUpdate.java new file mode 100644 index 0000000000000000000000000000000000000000..70d02527e25f03e7b183861664a55913aa413c07 --- /dev/null +++ b/dorive-core/src/main/java/com/gitee/dorive/core/entity/operation/InsertOrUpdate.java @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.gitee.dorive.core.entity.operation; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class InsertOrUpdate extends Operation { + + public InsertOrUpdate(Object entity) { + super(entity); + } + +} diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/entity/operation/Operation.java b/dorive-core/src/main/java/com/gitee/dorive/core/entity/operation/Operation.java index d496055315f2af129cbf8e380807070b425f0f5d..350d824c42adb08eb9c4cd274b8a525ce11b4794 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/entity/operation/Operation.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/entity/operation/Operation.java @@ -17,40 +17,42 @@ package com.gitee.dorive.core.entity.operation; -import com.gitee.dorive.api.constant.OperationType; import lombok.Data; @Data public class Operation { - public static final int UNKNOWN = 0; - public static final int INCLUDE_ROOT = 1; - public static final int IGNORE_ROOT = 2; + public enum RootControl {NONE, INCLUDE_ROOT, IGNORE_ROOT,} - private int type; + private RootControl rootControl = RootControl.NONE; private Object entity; - private int rootType; - public Operation(int type, Object entity) { - this.type = type; + public Operation(Object entity) { this.entity = entity; - this.rootType = UNKNOWN; } - public boolean isInsertContext() { - return (type & OperationType.INSERT) != 0; + public void includeRoot() { + rootControl = RootControl.INCLUDE_ROOT; } - public boolean isForceInsert() { - return type == OperationType.FORCE_INSERT; + public void ignoreRoot() { + rootControl = RootControl.IGNORE_ROOT; } public boolean isIncludeRoot() { - return rootType == 1; + return rootControl == RootControl.INCLUDE_ROOT; } public boolean isIgnoreRoot() { - return rootType == 2; + return rootControl == RootControl.IGNORE_ROOT; + } + + public void switchRoot(boolean flag) { + if (flag) { + includeRoot(); + } else { + ignoreRoot(); + } } } diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/entity/operation/Query.java b/dorive-core/src/main/java/com/gitee/dorive/core/entity/operation/Query.java index 84c40cdb4dbe2e9ff074b98ee1c5cdb600811390..c679a77d524928ee13f651b37fffd9cd2f908aeb 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/entity/operation/Query.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/entity/operation/Query.java @@ -17,7 +17,6 @@ package com.gitee.dorive.core.entity.operation; -import com.gitee.dorive.api.constant.OperationType; import lombok.Getter; import lombok.Setter; @@ -25,20 +24,12 @@ import lombok.Setter; @Setter public class Query extends Condition { - public Query(int type, Object entity) { - super(type, entity); - } - public Query(Object entity) { - super(OperationType.SELECT, entity); + super(entity); } public boolean isEmpty() { return getPrimaryKey() == null && getExample() == null; } - public boolean startPage() { - return getExample() != null && getExample().getPage() != null; - } - } diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/entity/operation/Update.java b/dorive-core/src/main/java/com/gitee/dorive/core/entity/operation/Update.java index da5dc6a9cc011e37322daf4619a4d1248e6a3e7c..bd514cd6c7f8f58a0766534c052fa41e977fd8b0 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/entity/operation/Update.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/entity/operation/Update.java @@ -17,20 +17,20 @@ package com.gitee.dorive.core.entity.operation; -import com.gitee.dorive.api.constant.OperationType; import lombok.Getter; import lombok.Setter; +import java.util.Collections; +import java.util.Set; + @Getter @Setter public class Update extends Condition { - public Update(int type, Object entity) { - super(type, entity); - } + private Set nullableProps = Collections.emptySet(); public Update(Object entity) { - super(OperationType.UPDATE, entity); + super(entity); } } diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/entity/option/JoinType.java b/dorive-core/src/main/java/com/gitee/dorive/core/entity/option/JoinType.java new file mode 100644 index 0000000000000000000000000000000000000000..0be2334a482f521471e2cd49dbd2241e74185ae5 --- /dev/null +++ b/dorive-core/src/main/java/com/gitee/dorive/core/entity/option/JoinType.java @@ -0,0 +1,25 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.gitee.dorive.core.entity.option; + +public enum JoinType { + UNKNOWN, + SINGLE, + MULTI, + UNION +} diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/entity/option/QueryMethod.java b/dorive-core/src/main/java/com/gitee/dorive/core/entity/option/QueryMethod.java new file mode 100644 index 0000000000000000000000000000000000000000..3f94c7f90023769cf2f4cfba3d2d84b330df4475 --- /dev/null +++ b/dorive-core/src/main/java/com/gitee/dorive/core/entity/option/QueryMethod.java @@ -0,0 +1,23 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.gitee.dorive.core.entity.option; + +public enum QueryMethod { + DEFAULT, + SQL +} diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/entity/option/SelectType.java b/dorive-core/src/main/java/com/gitee/dorive/core/entity/option/SelectType.java new file mode 100644 index 0000000000000000000000000000000000000000..468277897a9f0d8c894b63e65981c8fcc49f2d8a --- /dev/null +++ b/dorive-core/src/main/java/com/gitee/dorive/core/entity/option/SelectType.java @@ -0,0 +1,25 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.gitee.dorive.core.entity.option; + +public enum SelectType { + NONE, + ROOT, + ALL, + SELECTOR +} diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/impl/binder/AbstractBinder.java b/dorive-core/src/main/java/com/gitee/dorive/core/impl/binder/AbstractBinder.java index ee67e22cb9e76e03f160d5644ee0a4c0a81273d3..38c1c43ab4cc582abb1626bf2e44d3e7cafc7745 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/impl/binder/AbstractBinder.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/impl/binder/AbstractBinder.java @@ -20,7 +20,7 @@ package com.gitee.dorive.core.impl.binder; import com.gitee.dorive.api.entity.def.BindingDef; import com.gitee.dorive.api.entity.element.PropChain; import com.gitee.dorive.core.api.binder.Binder; -import com.gitee.dorive.core.api.binder.BindingProcessor; +import com.gitee.dorive.core.api.binder.Processor; import com.gitee.dorive.core.api.context.Context; import lombok.AllArgsConstructor; import lombok.Data; @@ -30,12 +30,12 @@ import java.util.List; @Data @AllArgsConstructor -public abstract class AbstractBinder implements Binder, BindingProcessor { +public abstract class AbstractBinder implements Binder, Processor { private BindingDef bindingDef; private String alias; private PropChain fieldPropChain; - private BindingProcessor bindingProcessor; + private Processor processor; public String getFieldName() { return fieldPropChain.getEntityField().getName(); @@ -53,12 +53,12 @@ public abstract class AbstractBinder implements Binder, BindingProcessor { @Override public Object input(Context context, Object value) { - return bindingProcessor.input(context, value); + return processor.input(context, value); } @Override public Object output(Context context, Object value) { - return bindingProcessor.output(context, value); + return processor.output(context, value); } public List collectFieldValues(Context context, List entities) { diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/impl/binder/ContextBinder.java b/dorive-core/src/main/java/com/gitee/dorive/core/impl/binder/ContextBinder.java index 950aea469fd4ef7d41fce5e441514c9387bbc5dc..30882a1f58989ba528fdc37bf80060421954a927 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/impl/binder/ContextBinder.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/impl/binder/ContextBinder.java @@ -18,23 +18,19 @@ package com.gitee.dorive.core.impl.binder; import com.gitee.dorive.api.entity.def.BindingDef; -import com.gitee.dorive.core.api.binder.BindingProcessor; -import com.gitee.dorive.core.api.context.Context; import com.gitee.dorive.api.entity.element.PropChain; - -import java.util.Map; +import com.gitee.dorive.core.api.binder.Processor; +import com.gitee.dorive.core.api.context.Context; public class ContextBinder extends AbstractBinder { - public ContextBinder(BindingDef bindingDef, String alias, PropChain fieldPropChain, BindingProcessor bindingProcessor) { - super(bindingDef, alias, fieldPropChain, bindingProcessor); + public ContextBinder(BindingDef bindingDef, String alias, PropChain fieldPropChain, Processor processor) { + super(bindingDef, alias, fieldPropChain, processor); } @Override public Object getBoundValue(Context context, Object rootEntity) { - Map attachments = context.getAttachments(); - String bindExp = getBindingDef().getBindExp(); - return attachments.get(bindExp); + return context.getAttachment(getBindingDef().getBindExp()); } @Override diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/impl/binder/PropertyBinder.java b/dorive-core/src/main/java/com/gitee/dorive/core/impl/binder/PropertyBinder.java index 6faee09b15d2be66a8f9afd58e7b212da28587db..3bb6dce54fbe410b3828fc26b8c225fbfa5afc18 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/impl/binder/PropertyBinder.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/impl/binder/PropertyBinder.java @@ -19,7 +19,7 @@ package com.gitee.dorive.core.impl.binder; import com.gitee.dorive.api.entity.def.BindingDef; import com.gitee.dorive.api.entity.element.PropChain; -import com.gitee.dorive.core.api.binder.BindingProcessor; +import com.gitee.dorive.core.api.binder.Processor; import com.gitee.dorive.core.api.context.Context; import com.gitee.dorive.core.repository.CommonRepository; import lombok.Getter; @@ -37,12 +37,12 @@ public class PropertyBinder extends AbstractBinder { public PropertyBinder(BindingDef bindingDef, String alias, PropChain fieldPropChain, - BindingProcessor bindingProcessor, + Processor processor, String belongAccessPath, CommonRepository belongRepository, PropChain boundPropChain, String bindAlias) { - super(bindingDef, alias, fieldPropChain, bindingProcessor); + super(bindingDef, alias, fieldPropChain, processor); this.belongAccessPath = belongAccessPath; this.belongRepository = belongRepository; this.boundPropChain = boundPropChain; diff --git a/dorive-event/src/main/java/com/gitee/dorive/event/impl/DefaultEntityListener.java b/dorive-core/src/main/java/com/gitee/dorive/core/impl/context/AbstractSelector.java similarity index 48% rename from dorive-event/src/main/java/com/gitee/dorive/event/impl/DefaultEntityListener.java rename to dorive-core/src/main/java/com/gitee/dorive/core/impl/context/AbstractSelector.java index 2799f34dae2cd52f7cea32aeadff48e531c4e788..ce1407e8351df7d90b89ec993d734450f9e80720 100644 --- a/dorive-event/src/main/java/com/gitee/dorive/event/impl/DefaultEntityListener.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/impl/context/AbstractSelector.java @@ -15,29 +15,41 @@ * limitations under the License. */ -package com.gitee.dorive.event.impl; +package com.gitee.dorive.core.impl.context; -import com.gitee.dorive.api.util.ReflectUtils; -import com.gitee.dorive.core.api.context.Context; -import com.gitee.dorive.core.entity.operation.Operation; -import com.gitee.dorive.event.api.EntityListener; -import com.gitee.dorive.event.entity.ExecutorEvent; +import com.gitee.dorive.core.api.context.Selector; +import com.gitee.dorive.core.entity.option.SelectType; -public abstract class DefaultEntityListener implements EntityListener { +import java.util.LinkedHashMap; +import java.util.Map; + +public abstract class AbstractSelector implements Selector { + + private final Map, Object> options = new LinkedHashMap<>(3); + + public AbstractSelector() { + this.options.put(SelectType.class, SelectType.SELECTOR); + this.options.put(Selector.class, this); + } @Override - public Class subscribe() { - return ReflectUtils.getFirstArgumentType(this.getClass()); + public Map, Object> getOptions() { + return options; } @Override - @SuppressWarnings("unchecked") - public void onApplicationEvent(ExecutorEvent executorEvent) { - Context context = executorEvent.getContext(); - Operation operation = executorEvent.getOperation(); - onExecution(context, operation.getType(), (E) operation.getEntity()); + public void setOption(Class type, Object value) { + throw new UnsupportedOperationException(); } - protected abstract void onExecution(Context context, int type, E entity); + @Override + public Object getOption(Class type) { + return options.get(type); + } + + @Override + public void removeOption(Class type) { + throw new UnsupportedOperationException(); + } } diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/impl/selector/NameSelector.java b/dorive-core/src/main/java/com/gitee/dorive/core/impl/context/NameSelector.java similarity index 72% rename from dorive-core/src/main/java/com/gitee/dorive/core/impl/selector/NameSelector.java rename to dorive-core/src/main/java/com/gitee/dorive/core/impl/context/NameSelector.java index db28324e791971240458ec4ac3d032c8220871ca..0f254292a524936641830a0784c800afb1646e90 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/impl/selector/NameSelector.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/impl/context/NameSelector.java @@ -15,53 +15,56 @@ * limitations under the License. */ -package com.gitee.dorive.core.impl.selector; +package com.gitee.dorive.core.impl.context; import cn.hutool.core.util.StrUtil; -import com.gitee.dorive.core.api.context.Context; -import com.gitee.dorive.core.api.context.Node; import lombok.AllArgsConstructor; import lombok.Data; import lombok.EqualsAndHashCode; -import org.apache.commons.lang3.StringUtils; import java.util.Collections; import java.util.LinkedHashMap; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.Set; @Data @EqualsAndHashCode(callSuper = false) public class NameSelector extends AbstractSelector { + private Set names = Collections.emptySet(); private Map nameDefMap = Collections.emptyMap(); public NameSelector(String... names) { if (names != null && names.length > 0) { - this.nameDefMap = new LinkedHashMap<>(names.length * 4 / 3 + 1); + int size = names.length * 4 / 3 + 1; + this.names = new LinkedHashSet<>(size); + this.nameDefMap = new LinkedHashMap<>(size); for (String name : names) { if (name.contains("(") && name.contains(")")) { String realName = name.substring(0, name.indexOf("(")); String propText = name.substring(name.indexOf("(") + 1, name.indexOf(")")); List properties = StrUtil.splitTrim(propText, ","); - nameDefMap.put(realName, new NameDef(realName, Collections.unmodifiableList(properties))); + this.names.add(realName); + this.nameDefMap.put(realName, new NameDef(realName, Collections.unmodifiableList(properties))); } else { - nameDefMap.put(name, new NameDef(name, Collections.emptyList())); + this.names.add(name); + this.nameDefMap.put(name, new NameDef(name, Collections.emptyList())); } } + this.names = Collections.unmodifiableSet(this.names); } } @Override - public boolean matches(Context context, Node node) { - String name = node.getName(); - return StringUtils.isBlank(name) || nameDefMap.containsKey(name); + public Set getNames() { + return names; } @Override - public List select(Context context, Node node) { - String name = node.getName(); + public List select(String name) { NameDef nameDef = nameDefMap.get(name); return nameDef != null && !nameDef.getProperties().isEmpty() ? nameDef.getProperties() : null; } diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/impl/context/SelectTypeMatcher.java b/dorive-core/src/main/java/com/gitee/dorive/core/impl/context/SelectTypeMatcher.java new file mode 100644 index 0000000000000000000000000000000000000000..d9f3048ee9ac4aa7853ebaba3385936d8f56ee3a --- /dev/null +++ b/dorive-core/src/main/java/com/gitee/dorive/core/impl/context/SelectTypeMatcher.java @@ -0,0 +1,75 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.gitee.dorive.core.impl.context; + +import com.gitee.dorive.core.api.context.Context; +import com.gitee.dorive.core.api.context.Matcher; +import com.gitee.dorive.core.api.context.Selector; +import com.gitee.dorive.core.entity.option.SelectType; +import com.gitee.dorive.core.repository.CommonRepository; +import lombok.Getter; +import lombok.Setter; + +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; + +/** + * 双向依赖,在获取hashCode时,会栈溢出 + */ +@Getter +@Setter +public class SelectTypeMatcher implements Matcher { + + private CommonRepository repository; + private Map matcherMap = new LinkedHashMap<>(8); + + public SelectTypeMatcher(CommonRepository repository) { + this.repository = repository; + this.matcherMap.put(SelectType.NONE, context -> false); + this.matcherMap.put(SelectType.ROOT, context -> repository.isRoot()); + this.matcherMap.put(SelectType.ALL, context -> true); + this.matcherMap.put(SelectType.SELECTOR, new SelectorMatcher()); + } + + @Override + public boolean matches(Context context) { + SelectType selectType = (SelectType) context.getOption(SelectType.class); + if (selectType != null) { + Matcher matcher = matcherMap.get(selectType); + if (matcher != null) { + return matcher.matches(context); + } + } + return false; + } + + private class SelectorMatcher implements Matcher { + @Override + public boolean matches(Context context) { + Selector selector = (Selector) context.getOption(Selector.class); + if (selector != null) { + Set names = selector.getNames(); + String name = repository.getName(); + return names.contains(name); + } + return false; + } + } + +} diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/impl/converter/DefaultFieldConverter.java b/dorive-core/src/main/java/com/gitee/dorive/core/impl/converter/DefaultConverter.java similarity index 71% rename from dorive-core/src/main/java/com/gitee/dorive/core/impl/converter/DefaultFieldConverter.java rename to dorive-core/src/main/java/com/gitee/dorive/core/impl/converter/DefaultConverter.java index 8f6eda212c7cc02aa646fd127eed7e1488a41c19..754dfd4c92bcffcaf5e8b843efed19a86a38b64f 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/impl/converter/DefaultFieldConverter.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/impl/converter/DefaultConverter.java @@ -20,26 +20,23 @@ package com.gitee.dorive.core.impl.converter; import cn.hutool.core.util.StrUtil; import com.gitee.dorive.api.entity.def.FieldDef; import com.gitee.dorive.api.entity.element.EntityField; -import com.gitee.dorive.core.api.context.Context; -import com.gitee.dorive.core.api.executor.FieldConverter; -import com.gitee.dorive.core.entity.executor.Criterion; +import com.gitee.dorive.core.api.converter.Converter; import lombok.Data; import org.apache.commons.lang3.StringUtils; -import java.util.ArrayList; import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @Data -public class DefaultFieldConverter implements FieldConverter { +public class DefaultConverter implements Converter { private EntityField entityField; private Map reMapping = Collections.emptyMap(); private Map deMapping = Collections.emptyMap(); - public DefaultFieldConverter(EntityField entityField) { + public DefaultConverter(EntityField entityField) { this.entityField = entityField; FieldDef fieldDef = entityField.getFieldDef(); Class genericType = entityField.getGenericType(); @@ -66,33 +63,7 @@ public class DefaultFieldConverter implements FieldConverter { } } - @Override - public Object convert(Context context, Criterion criterion, Object value) { - if (value == null) { - return null; - } - if (value instanceof List) { - List list = (List) value; - List newList = new ArrayList<>(list.size()); - for (Object item : list) { - Object mapValue = deMapping.get(item); - if (mapValue != null) { - newList.add(mapValue); - } else { - newList.add(item); - } - } - return newList; - } - Object mapValue = deMapping.get(value); - if (mapValue != null) { - return mapValue; - } - return value; - } - - @Override - public Object reconstitute(String name, Object value) { + public Object reconstitute(Object value) { if (value == null) { return null; } @@ -103,8 +74,7 @@ public class DefaultFieldConverter implements FieldConverter { return value; } - @Override - public Object deconstruct(String name, Object value) { + public Object deconstruct(Object value) { if (value == null) { return null; } diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/impl/factory/DefaultEntityFactory.java b/dorive-core/src/main/java/com/gitee/dorive/core/impl/converter/DefaultEntityFactory.java similarity index 50% rename from dorive-core/src/main/java/com/gitee/dorive/core/impl/factory/DefaultEntityFactory.java rename to dorive-core/src/main/java/com/gitee/dorive/core/impl/converter/DefaultEntityFactory.java index 680e68563ea29925ff80897fd3b119717f6989cc..fea4808f6c5332c79db5c322502b379e27daf9bd 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/impl/factory/DefaultEntityFactory.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/impl/converter/DefaultEntityFactory.java @@ -15,57 +15,47 @@ * limitations under the License. */ -package com.gitee.dorive.core.impl.factory; +package com.gitee.dorive.core.impl.converter; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.copier.CopyOptions; import com.gitee.dorive.api.entity.element.EntityEle; import com.gitee.dorive.core.api.context.Context; -import com.gitee.dorive.core.api.executor.FieldConverter; -import com.gitee.dorive.core.api.executor.EntityFactory; +import com.gitee.dorive.core.api.converter.EntityFactory; +import com.gitee.dorive.core.api.converter.EntityMapper; +import com.gitee.dorive.core.entity.common.EntityStoreInfo; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; -import java.util.Map; - @Data @NoArgsConstructor @AllArgsConstructor public class DefaultEntityFactory implements EntityFactory { private EntityEle entityEle; - private Class pojoClass; - - private Map aliasFieldMapping; - private Map fieldConverterMap; + private EntityStoreInfo entityStoreInfo; + private EntityMapper entityMapper; private CopyOptions reCopyOptions; - - private Map fieldPropMapping; - private Map propConverterMap; private CopyOptions deCopyOptions; - public void setReCopyOptions(Map aliasFieldMapping, Map fieldConverterMap) { - this.aliasFieldMapping = aliasFieldMapping; - this.fieldConverterMap = fieldConverterMap; - this.reCopyOptions = CopyOptions.create().ignoreNullValue().setFieldMapping(aliasFieldMapping); - if (fieldConverterMap != null && !fieldConverterMap.isEmpty()) { - this.reCopyOptions.setFieldValueEditor((name, value) -> { - FieldConverter fieldConverter = fieldConverterMap.get(name); - return fieldConverter != null ? fieldConverter.reconstitute(name, value) : value; - }); + public void setEntityMapper(EntityMapper entityMapper) { + this.entityMapper = entityMapper; + initReCopyOptions(); + initDeCopyOptions(); + } + + private void initReCopyOptions() { + this.reCopyOptions = CopyOptions.create().ignoreNullValue().setFieldNameEditor(entityMapper::aliasToField); + if (entityMapper.hasConverter()) { + this.reCopyOptions.setFieldValueEditor((field, value) -> entityMapper.aliasToField(field, value)); } } - public void setDeCopyOptions(Map fieldPropMapping, Map propConverterMap) { - this.fieldPropMapping = fieldPropMapping; - this.propConverterMap = propConverterMap; - this.deCopyOptions = CopyOptions.create().ignoreNullValue().setFieldMapping(fieldPropMapping); - if (propConverterMap != null && !propConverterMap.isEmpty()) { - this.deCopyOptions.setFieldValueEditor((name, value) -> { - FieldConverter fieldConverter = propConverterMap.get(name); - return fieldConverter != null ? fieldConverter.deconstruct(name, value) : value; - }); + private void initDeCopyOptions() { + this.deCopyOptions = CopyOptions.create().ignoreNullValue().setFieldNameEditor(entityMapper::fieldToProp); + if (entityMapper.hasConverter()) { + this.deCopyOptions.setFieldValueEditor((prop, value) -> entityMapper.fieldToProp(prop, value)); } } @@ -76,7 +66,7 @@ public class DefaultEntityFactory implements EntityFactory { @Override public Object deconstruct(Context context, Object entity) { - return BeanUtil.toBean(entity, pojoClass, deCopyOptions); + return BeanUtil.toBean(entity, entityStoreInfo.getPojoClass(), deCopyOptions); } } diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/impl/converter/DefaultEntityMapper.java b/dorive-core/src/main/java/com/gitee/dorive/core/impl/converter/DefaultEntityMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..a453e57354f27da14a209da387144c5e89600cc9 --- /dev/null +++ b/dorive-core/src/main/java/com/gitee/dorive/core/impl/converter/DefaultEntityMapper.java @@ -0,0 +1,99 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.gitee.dorive.core.impl.converter; + +import com.gitee.dorive.core.api.converter.Converter; +import com.gitee.dorive.core.api.converter.EntityMapper; +import lombok.AllArgsConstructor; +import lombok.Data; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +@Data +@AllArgsConstructor +public class DefaultEntityMapper implements EntityMapper { + + private Map fieldAliasMapping; + private Map aliasFieldMapping; + private Map fieldPropMapping; + private Map fieldConverterMap; + private Map aliasConverterMap; + private Map propConverterMap; + + @Override + public String fieldToAlias(String field) { + return fieldAliasMapping.get(field); + } + + @Override + public String aliasToField(String alias) { + return aliasFieldMapping.get(alias); + } + + @Override + public String fieldToProp(String field) { + return fieldPropMapping.get(field); + } + + @Override + public boolean hasConverter() { + return fieldConverterMap != null && !fieldConverterMap.isEmpty(); + } + + @Override + public Object fieldToAlias(String alias, Object value) { + Converter converter = aliasConverterMap.get(alias); + if (converter != null) { + if (value instanceof List) { + List list = (List) value; + List newList = new ArrayList<>(list.size()); + for (Object item : list) { + Object mapValue = converter.deconstruct(item); + if (mapValue != null) { + newList.add(mapValue); + } else { + newList.add(item); + } + } + return newList; + + } else { + Object mapValue = converter.deconstruct(value); + if (mapValue != null) { + return mapValue; + } + } + } + return value; + } + + @Override + public Object aliasToField(String field, Object value) { + Converter converter = fieldConverterMap.get(field); + return converter != null ? converter.reconstitute(value) : value; + } + + @Override + public Object fieldToProp(String prop, Object value) { + Converter converter = propConverterMap.get(prop); + return converter != null ? converter.deconstruct(value) : value; + } + +} diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/impl/executor/AbstractExecutor.java b/dorive-core/src/main/java/com/gitee/dorive/core/impl/executor/AbstractExecutor.java index a5d0456d4fc717e02667ed188693961c995cfcb3..cc1ddd336101ccfba1704234aeb8aa30df0065bf 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/impl/executor/AbstractExecutor.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/impl/executor/AbstractExecutor.java @@ -18,8 +18,10 @@ package com.gitee.dorive.core.impl.executor; import com.gitee.dorive.core.api.executor.Executor; -import lombok.Data; +import lombok.Getter; +import lombok.Setter; -@Data +@Getter +@Setter public abstract class AbstractExecutor implements Executor { } diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/impl/executor/AbstractProxyExecutor.java b/dorive-core/src/main/java/com/gitee/dorive/core/impl/executor/AbstractProxyExecutor.java index 92f4fac2097185b3fcb5c8b0fc20616c88da5c43..45ee4fdae94189aa0ae530477fe7ac4e1b7dfc68 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/impl/executor/AbstractProxyExecutor.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/impl/executor/AbstractProxyExecutor.java @@ -23,14 +23,14 @@ import com.gitee.dorive.core.entity.executor.Result; import com.gitee.dorive.core.entity.operation.Operation; import com.gitee.dorive.core.entity.operation.Query; import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.EqualsAndHashCode; +import lombok.Getter; import lombok.NoArgsConstructor; +import lombok.Setter; -@Data +@Getter +@Setter @NoArgsConstructor @AllArgsConstructor -@EqualsAndHashCode(callSuper = false) public abstract class AbstractProxyExecutor extends AbstractExecutor { private Executor executor; diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/impl/executor/DefaultExecutor.java b/dorive-core/src/main/java/com/gitee/dorive/core/impl/executor/ContextExecutor.java similarity index 36% rename from dorive-core/src/main/java/com/gitee/dorive/core/impl/executor/DefaultExecutor.java rename to dorive-core/src/main/java/com/gitee/dorive/core/impl/executor/ContextExecutor.java index 40696f8e9e777274ad0d11ef195c577eee96971e..c1d8d7015efa96be7658fcd04ebeb579a5dcdec4 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/impl/executor/DefaultExecutor.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/impl/executor/ContextExecutor.java @@ -18,34 +18,38 @@ package com.gitee.dorive.core.impl.executor; import cn.hutool.core.lang.Assert; -import com.gitee.dorive.api.constant.OperationType; import com.gitee.dorive.api.entity.element.PropChain; import com.gitee.dorive.core.api.binder.Binder; import com.gitee.dorive.core.api.context.Context; -import com.gitee.dorive.core.api.context.Selector; import com.gitee.dorive.core.api.executor.EntityHandler; +import com.gitee.dorive.core.api.executor.Executor; import com.gitee.dorive.core.entity.executor.Result; +import com.gitee.dorive.core.entity.operation.Delete; +import com.gitee.dorive.core.entity.operation.Insert; +import com.gitee.dorive.core.entity.operation.InsertOrUpdate; import com.gitee.dorive.core.entity.operation.Operation; import com.gitee.dorive.core.entity.operation.Query; +import com.gitee.dorive.core.entity.operation.Update; import com.gitee.dorive.core.impl.factory.OperationFactory; import com.gitee.dorive.core.impl.resolver.DerivedResolver; import com.gitee.dorive.core.repository.AbstractContextRepository; import com.gitee.dorive.core.repository.CommonRepository; -import lombok.Data; -import lombok.EqualsAndHashCode; +import com.gitee.dorive.core.util.CollectionUtils; +import lombok.Getter; +import lombok.Setter; import java.util.Collection; -import java.util.Collections; import java.util.List; +import java.util.Map; -@Data -@EqualsAndHashCode(callSuper = false) -public class DefaultExecutor extends AbstractExecutor implements EntityHandler { +@Getter +@Setter +public class ContextExecutor extends AbstractExecutor { private final AbstractContextRepository repository; private final EntityHandler entityHandler; - public DefaultExecutor(AbstractContextRepository repository, EntityHandler entityHandler) { + public ContextExecutor(AbstractContextRepository repository, EntityHandler entityHandler) { this.repository = repository; this.entityHandler = entityHandler; } @@ -53,22 +57,36 @@ public class DefaultExecutor extends AbstractExecutor implements EntityHandler { @Override public Result executeQuery(Context context, Query query) { Assert.isTrue(!query.isEmpty(), "The query cannot be empty!"); - Selector selector = context.getSelector(); CommonRepository rootRepository = repository.getRootRepository(); - if (selector.matches(context, rootRepository) || query.isIncludeRoot()) { + if (rootRepository.matches(context) || query.isIncludeRoot()) { Result result = rootRepository.executeQuery(context, query); List entities = result.getRecords(); if (!entities.isEmpty()) { - handle(context, entities); + populate(context, entities); } return result; } return new Result<>(); } - @Override - public long handle(Context context, List entities) { - return entityHandler.handle(context, entities); + public void populate(Context context, List entities) { + DerivedResolver derivedResolver = repository.getDerivedResolver(); + if (!derivedResolver.hasDerived()) { + entityHandler.handle(context, entities); + } else { + Map, List> repositoryEntitiesMap = derivedResolver.distribute(entities); + repositoryEntitiesMap.forEach((repository, partEntities) -> { + if (repository == this.repository) { // 避免自循环 + entityHandler.handle(context, partEntities); + } else { + Executor executor = repository.getExecutor(); + if (executor instanceof ContextExecutor) { + ContextExecutor contextExecutor = (ContextExecutor) executor; + contextExecutor.populate(context, partEntities); + } + } + }); + } } @Override @@ -78,85 +96,163 @@ public class DefaultExecutor extends AbstractExecutor implements EntityHandler { @Override public int execute(Context context, Operation operation) { - Selector selector = context.getSelector(); - - boolean isInsertContext = operation.isInsertContext(); - boolean isIncludeRoot = operation.isIncludeRoot(); - boolean isIgnoreRoot = operation.isIgnoreRoot(); - Object rootEntity = operation.getEntity(); Assert.notNull(rootEntity, "The root entity cannot be null!"); DerivedResolver derivedResolver = repository.getDerivedResolver(); - AbstractContextRepository delegateRepository = derivedResolver.deriveRepository(rootEntity); - delegateRepository = delegateRepository == null ? repository : delegateRepository; + AbstractContextRepository repository = derivedResolver.distribute(rootEntity); + + Executor executor = repository.getExecutor(); + if (executor instanceof ContextExecutor) { + ContextExecutor contextExecutor = (ContextExecutor) executor; + if (operation instanceof Insert) { + return contextExecutor.executeInsert(context, operation); + } else if (operation instanceof Update || operation instanceof Delete) { + return contextExecutor.executeUpdateOrDelete(context, operation); + + } else if (operation instanceof InsertOrUpdate) { + return contextExecutor.executeInsertOrUpdate(context, operation); + } + } + return 0; + } + + public int executeInsert(Context context, Operation operation) { + Object rootEntity = operation.getEntity(); int totalCount = 0; - for (CommonRepository repository : delegateRepository.getOrderedRepositories()) { - boolean isRoot = repository.isRoot(); - if (isIgnoreRoot && isRoot) { - continue; + for (CommonRepository repository : this.repository.getOrderedRepositories()) { + if (repository.isRoot()) { + if (!operation.isIgnoreRoot()) { + if (repository.matches(context) || operation.isIncludeRoot()) { + getBoundValue(context, rootEntity, repository, rootEntity); + totalCount += repository.execute(context, operation); + setBoundId(context, rootEntity, repository, rootEntity); + } + } + } else { + boolean isMatch = repository.matches(context); + boolean isAggregated = repository.isAggregated(); + if (!isMatch && !isAggregated) { + continue; + } + PropChain anchorPoint = repository.getAnchorPoint(); + Object targetEntity = anchorPoint.getValue(rootEntity); + if (targetEntity == null) { + continue; + } + OperationFactory operationFactory = repository.getOperationFactory(); + Collection collection = CollectionUtils.toCollection(targetEntity); + for (Object entity : collection) { + if (isMatch) { + getBoundValue(context, rootEntity, repository, entity); + } + Operation newOperation = operationFactory.buildInsert(entity); + newOperation.switchRoot(isMatch); + totalCount += repository.execute(context, newOperation); + } + if (collection.size() == 1) { + setBoundId(context, rootEntity, repository, collection.iterator().next()); + } } + } + return totalCount; + } - boolean isMatch = selector.matches(context, repository) || (isIncludeRoot && isRoot); - boolean isAggregated = repository.isAggregated(); + public int executeUpdateOrDelete(Context context, Operation operation) { + Object rootEntity = operation.getEntity(); + int totalCount = 0; + if (!operation.isIgnoreRoot()) { + CommonRepository rootRepository = this.repository.getRootRepository(); + if (rootRepository.matches(context) || operation.isIncludeRoot()) { + Object primaryKey = rootRepository.getPrimaryKey(rootEntity); + if (primaryKey != null) { + totalCount += rootRepository.execute(context, operation); + } + } + } + for (CommonRepository subRepository : this.repository.getSubRepositories()) { + boolean isMatch = subRepository.matches(context); + boolean isAggregated = subRepository.isAggregated(); if (!isMatch && !isAggregated) { continue; } + PropChain anchorPoint = subRepository.getAnchorPoint(); + Object targetEntity = anchorPoint.getValue(rootEntity); + if (targetEntity == null) { + continue; + } + OperationFactory operationFactory = subRepository.getOperationFactory(); + Collection collection = CollectionUtils.toCollection(targetEntity); + for (Object entity : collection) { + Object primaryKey = subRepository.getPrimaryKey(entity); + Operation newOperation = null; + if ((isMatch && primaryKey != null) || isAggregated) { + newOperation = operation instanceof Update ? operationFactory.buildUpdate(entity) : operationFactory.buildDelete(entity); + } + if (newOperation != null) { + newOperation.switchRoot(isMatch); + totalCount += subRepository.execute(context, newOperation); + } + } + } + return totalCount; + } - PropChain anchorPoint = repository.getAnchorPoint(); - Object targetEntity = isRoot ? rootEntity : anchorPoint.getValue(rootEntity); - if (targetEntity != null) { - Collection collection; - if (targetEntity instanceof Collection) { - collection = (Collection) targetEntity; - } else { - collection = Collections.singletonList(targetEntity); + public int executeInsertOrUpdate(Context context, Operation operation) { + Object rootEntity = operation.getEntity(); + int totalCount = 0; + for (CommonRepository repository : this.repository.getOrderedRepositories()) { + OperationFactory operationFactory = repository.getOperationFactory(); + if (repository.isRoot()) { + if (!operation.isIgnoreRoot()) { + if (repository.matches(context) || operation.isIncludeRoot()) { + Operation newOperation = operationFactory.buildInsertOrUpdate(rootEntity); + if (newOperation instanceof Insert) { + getBoundValue(context, rootEntity, repository, rootEntity); + totalCount += repository.execute(context, newOperation); + setBoundId(context, rootEntity, repository, rootEntity); + } else { + totalCount += repository.execute(context, newOperation); + } + } + } + } else { + boolean isMatch = repository.matches(context); + boolean isAggregated = repository.isAggregated(); + if (!isMatch && !isAggregated) { + continue; } + PropChain anchorPoint = repository.getAnchorPoint(); + Object targetEntity = anchorPoint.getValue(rootEntity); + if (targetEntity == null) { + continue; + } + Collection collection = CollectionUtils.toCollection(targetEntity); + Object onlyOne = collection.size() == 1 ? collection.iterator().next() : null; + boolean isOnlyOneInsert = onlyOne != null && repository.getPrimaryKey(onlyOne) == null; for (Object entity : collection) { - int operationType = OperationType.NONE; - boolean operable = false; - if (isMatch) { - operationType = determineType(operation, repository, entity); - operable = (operationType & OperationType.INSERT_OR_UPDATE_OR_DELETE) != 0; - if ((operationType & OperationType.INSERT) != 0) { - getBoundValue(context, rootEntity, repository, entity); - } + Object primaryKey = repository.getPrimaryKey(entity); + if (isMatch && primaryKey == null) { + getBoundValue(context, rootEntity, repository, entity); } + Operation newOperation; if (isAggregated) { - OperationFactory operationFactory = repository.getOperationFactory(); - Operation newOperation = operationFactory.renewOperation(operation, entity); - if (newOperation != null) { - newOperation.setRootType(operable ? Operation.INCLUDE_ROOT : Operation.IGNORE_ROOT); - totalCount += repository.execute(context, newOperation); - } - - } else if (operable) { - if (isRoot && operation.getType() == operationType) { - totalCount += repository.execute(context, operation); - } else { - totalCount += doExecute(context, repository, entity, operationType); - } + newOperation = new InsertOrUpdate(entity); + } else { + newOperation = primaryKey == null ? operationFactory.buildInsert(entity) : operationFactory.buildUpdate(entity); } + newOperation.switchRoot(isMatch); + totalCount += repository.execute(context, newOperation); } - if (isInsertContext && collection.size() == 1) { - setBoundId(context, rootEntity, repository, targetEntity); + if (isOnlyOneInsert) { + setBoundId(context, rootEntity, repository, onlyOne); } } } return totalCount; } - private int determineType(Operation operation, CommonRepository repository, Object entity) { - if (operation.isForceInsert()) { - return OperationType.INSERT; - } - int type = operation.getType(); - Object primaryKey = repository.getPrimaryKey(entity); - int operationType = primaryKey == null ? OperationType.INSERT : OperationType.UPDATE_OR_DELETE; - return type & operationType; - } - private void getBoundValue(Context context, Object rootEntity, CommonRepository repository, Object entity) { for (Binder binder : repository.getBinderResolver().getBoundValueBinders()) { Object fieldValue = binder.getFieldValue(context, entity); @@ -169,19 +265,6 @@ public class DefaultExecutor extends AbstractExecutor implements EntityHandler { } } - private int doExecute(Context context, CommonRepository repository, Object entity, int operationType) { - if (operationType == OperationType.INSERT) { - return repository.insert(context, entity); - - } else if (operationType == OperationType.UPDATE) { - return repository.update(context, entity); - - } else if (operationType == OperationType.DELETE) { - return repository.delete(context, entity); - } - return 0; - } - private void setBoundId(Context context, Object rootEntity, CommonRepository repository, Object entity) { Binder binder = repository.getBinderResolver().getBoundIdBinder(); if (binder != null) { diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/impl/executor/AbstractExampleExecutor.java b/dorive-core/src/main/java/com/gitee/dorive/core/impl/executor/ExampleExecutor.java similarity index 41% rename from dorive-core/src/main/java/com/gitee/dorive/core/impl/executor/AbstractExampleExecutor.java rename to dorive-core/src/main/java/com/gitee/dorive/core/impl/executor/ExampleExecutor.java index bde74464b4da0e405e29a0201c0e887ab6eb86f9..2836a285f480ba4957dbc866d590fdd52c6da733 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/impl/executor/AbstractExampleExecutor.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/impl/executor/ExampleExecutor.java @@ -17,38 +17,47 @@ package com.gitee.dorive.core.impl.executor; +import com.gitee.dorive.api.constant.Operator; +import com.gitee.dorive.api.entity.element.EntityEle; import com.gitee.dorive.core.api.context.Context; +import com.gitee.dorive.core.api.converter.EntityMapper; import com.gitee.dorive.core.api.executor.Executor; +import com.gitee.dorive.core.entity.executor.Criterion; import com.gitee.dorive.core.entity.executor.Example; +import com.gitee.dorive.core.entity.executor.OrderBy; import com.gitee.dorive.core.entity.executor.Result; import com.gitee.dorive.core.entity.executor.UnionExample; import com.gitee.dorive.core.entity.operation.Condition; import com.gitee.dorive.core.entity.operation.Operation; import com.gitee.dorive.core.entity.operation.Query; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.NoArgsConstructor; +import com.gitee.dorive.core.entity.operation.Update; +import lombok.Getter; +import lombok.Setter; import java.util.List; +import java.util.Set; -@Data -@NoArgsConstructor -@EqualsAndHashCode(callSuper = false) -public abstract class AbstractExampleExecutor extends AbstractProxyExecutor { +@Getter +@Setter +public class ExampleExecutor extends AbstractProxyExecutor { - public AbstractExampleExecutor(Executor executor) { + private EntityEle entityEle; + private EntityMapper entityMapper; + + public ExampleExecutor(Executor executor, EntityEle entityEle, EntityMapper entityMapper) { super(executor); + this.entityEle = entityEle; + this.entityMapper = entityMapper; } @Override public Result executeQuery(Context context, Query query) { Example example = query.getExample(); if (example != null) { - if (example instanceof UnionExample) { - convert(context, (UnionExample) example); - } else { - convert(context, example); - } + convert(context, example); + } + if (example instanceof UnionExample) { + convertUnion(context, (UnionExample) example); } return super.executeQuery(context, query); } @@ -71,16 +80,80 @@ public abstract class AbstractExampleExecutor extends AbstractProxyExecutor { convert(context, example); } } + if (operation instanceof Update) { + convertUpdate((Update) operation); + } return super.execute(context, operation); } - private void convert(Context context, UnionExample unionExample) { + public void convert(Context context, Example example) { + convertSelectProps(example); + convertCriteria(context, example); + convertOrderBy(example); + } + + private void convertUnion(Context context, UnionExample unionExample) { List examples = unionExample.getExamples(); for (Example example : examples) { - convert(context, example); + convertCriteria(context, example); + } + } + + private void convertUpdate(Update update) { + Set nullableProps = update.getNullableProps(); + if (nullableProps != null && !nullableProps.isEmpty()) { + nullableProps = entityEle.toAliases(nullableProps); + update.setNullableProps(nullableProps); } } - public abstract void convert(Context context, Example example); + private void convertSelectProps(Example example) { + List properties = example.getSelectProps(); + if (properties != null && !properties.isEmpty()) { + properties = entityEle.toAliases(properties); + example.setSelectProps(properties); + } + } + + private void convertCriteria(Context context, Example example) { + List criteria = example.getCriteria(); + if (criteria != null && !criteria.isEmpty()) { + for (Criterion criterion : criteria) { + String operator = criterion.getOperator(); + if (Operator.AND.equals(operator) || Operator.OR.equals(operator)) { + Object value = criterion.getValue(); + if (value instanceof Example) { + convert(context, (Example) value); + } + } else { + doConvertCriteria(criterion); + } + } + } + } + + private void doConvertCriteria(Criterion criterion) { + String property = criterion.getProperty(); + String alias = entityMapper.fieldToAlias(property); + if (alias != null) { + criterion.setProperty(alias); + } else { + alias = property; + } + if (entityMapper.hasConverter()) { + Object value = criterion.getValue(); + value = entityMapper.fieldToAlias(alias, value); + criterion.setValue(value); + } + } + + private void convertOrderBy(Example example) { + OrderBy orderBy = example.getOrderBy(); + if (orderBy != null) { + List properties = orderBy.getProperties(); + properties = entityEle.toAliases(properties); + orderBy.setProperties(properties); + } + } } diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/impl/executor/FactoryExecutor.java b/dorive-core/src/main/java/com/gitee/dorive/core/impl/executor/FactoryExecutor.java index 804dee38bf743ec3d169acc39dfd51c7cddbd690..29f982f041428198663983b56785db071260a999 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/impl/executor/FactoryExecutor.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/impl/executor/FactoryExecutor.java @@ -20,85 +20,69 @@ package com.gitee.dorive.core.impl.executor; import cn.hutool.core.bean.BeanUtil; import com.gitee.dorive.api.entity.element.EntityEle; import com.gitee.dorive.core.api.context.Context; -import com.gitee.dorive.core.api.executor.EntityFactory; +import com.gitee.dorive.core.api.converter.EntityFactory; import com.gitee.dorive.core.api.executor.Executor; -import com.gitee.dorive.core.entity.executor.*; +import com.gitee.dorive.core.entity.common.EntityStoreInfo; +import com.gitee.dorive.core.entity.executor.Example; +import com.gitee.dorive.core.entity.executor.Page; +import com.gitee.dorive.core.entity.executor.Result; +import com.gitee.dorive.core.entity.executor.UnionExample; import com.gitee.dorive.core.entity.operation.Insert; import com.gitee.dorive.core.entity.operation.Operation; import com.gitee.dorive.core.entity.operation.Query; -import lombok.Data; -import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; -@Data -@EqualsAndHashCode(callSuper = false) +@Getter +@Setter public class FactoryExecutor extends AbstractProxyExecutor { private EntityEle entityEle; + private EntityStoreInfo entityStoreInfo; private EntityFactory entityFactory; - public FactoryExecutor(Executor executor, EntityEle entityEle, EntityFactory entityFactory) { + public FactoryExecutor(Executor executor, EntityEle entityEle, EntityStoreInfo entityStoreInfo, EntityFactory entityFactory) { super(executor); this.entityEle = entityEle; + this.entityStoreInfo = entityStoreInfo; this.entityFactory = entityFactory; } @Override public Result executeQuery(Context context, Query query) { Result result = super.executeQuery(context, query); - MultiResult multiResult = (MultiResult) result; - Page page = multiResult.getPage(); - List> resultMaps = multiResult.getResultMaps(); + Page page = result.getPage(); + List> recordMaps = result.getRecordMaps(); List entities = Collections.emptyList(); - if (resultMaps != null && !resultMaps.isEmpty()) { - Example example = query.getExample(); - if (example instanceof UnionExample) { - entities = reconstituteWithoutDuplicate(context, resultMaps); - } else { - entities = reconstitute(context, resultMaps); - } + if (recordMaps != null && !recordMaps.isEmpty()) { + entities = reconstitute(context, query, recordMaps); } if (page != null) { page.setRecords(entities); } - multiResult.setRecords(entities); - multiResult.setRecord(!entities.isEmpty() ? entities.get(0) : null); - multiResult.setCount(entities.size()); - return multiResult; - } - - private List reconstituteWithoutDuplicate(Context context, List> resultMaps) { - int size = resultMaps.size(); - List entities = new ArrayList<>(size); - Map existEntityMap = new LinkedHashMap<>(size * 4 / 3 + 1); - for (Map resultMap : resultMaps) { - Object id = resultMap.get("id"); - Object entity = null; - if (id != null) { - entity = existEntityMap.get(String.valueOf(id)); - } - if (entity == null) { - entity = entityFactory.reconstitute(context, resultMap); - if (id != null) { - existEntityMap.put(String.valueOf(id), entity); - } - entities.add(entity); - } - if (entity != null) { - resultMap.put("$entity", entity); - } - } - return entities; + result.setRecords(entities); + result.setRecord(!entities.isEmpty() ? entities.get(0) : null); + result.setCount(entities.size()); + return result; } - private List reconstitute(Context context, List> resultMaps) { + private List reconstitute(Context context, Query query, List> resultMaps) { + Example example = query.getExample(); + boolean isUnion = example instanceof UnionExample; List entities = new ArrayList<>(resultMaps.size()); for (Map resultMap : resultMaps) { Object entity = entityFactory.reconstitute(context, resultMap); if (entity != null) { + if (isUnion) { + resultMap.put("$entity", entity); + } entities.add(entity); } } @@ -115,8 +99,10 @@ public class FactoryExecutor extends AbstractProxyExecutor { int totalCount = super.execute(context, operation); if (operation instanceof Insert) { Object persistent = operation.getEntity(); - Object primaryKey = BeanUtil.getFieldValue(persistent, "id"); - entityEle.getPkProxy().setValue(entity, primaryKey); + Object primaryKey = BeanUtil.getFieldValue(persistent, entityStoreInfo.getIdProperty()); + if (primaryKey != null) { + entityEle.getIdProxy().setValue(entity, primaryKey); + } } operation.setEntity(entity); return totalCount; diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/impl/executor/FieldExecutor.java b/dorive-core/src/main/java/com/gitee/dorive/core/impl/executor/FieldExecutor.java deleted file mode 100644 index 2123456356758626d3faf9cc5712f0e79e912184..0000000000000000000000000000000000000000 --- a/dorive-core/src/main/java/com/gitee/dorive/core/impl/executor/FieldExecutor.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.gitee.dorive.core.impl.executor; - -import com.gitee.dorive.api.entity.element.EntityEle; -import com.gitee.dorive.core.api.context.Context; -import com.gitee.dorive.core.api.executor.Executor; -import com.gitee.dorive.core.api.executor.FieldConverter; -import com.gitee.dorive.core.entity.executor.Criterion; -import com.gitee.dorive.core.entity.executor.Example; -import com.gitee.dorive.core.entity.executor.OrderBy; -import lombok.Data; -import lombok.EqualsAndHashCode; - -import java.util.List; -import java.util.Map; - -@Data -@EqualsAndHashCode(callSuper = false) -public class FieldExecutor extends AbstractExampleExecutor { - - private EntityEle entityEle; - private Map converterMap; - - public FieldExecutor(Executor executor, EntityEle entityEle, Map converterMap) { - super(executor); - this.entityEle = entityEle; - this.converterMap = converterMap; - } - - @Override - public void convert(Context context, Example example) { - convertSelectProps(example); - convertCriteria(context, example.getCriteria()); - convertOrderBy(example.getOrderBy()); - } - - public void convertSelectProps(Example example) { - List properties = example.getSelectProps(); - if (properties != null && !properties.isEmpty()) { - properties = entityEle.toAliases(properties); - example.setSelectProps(properties); - } - } - - public void convertCriteria(Context context, List criteria) { - if (criteria != null && !criteria.isEmpty()) { - for (Criterion criterion : criteria) { - String property = criterion.getProperty(); - String alias = entityEle.toAlias(property); - criterion.setProperty(alias); - - Object value = criterion.getValue(); - if (converterMap != null && !converterMap.isEmpty()) { - FieldConverter fieldConverter = converterMap.get(property); - if (fieldConverter != null) { - Object mappedValue = fieldConverter.convert(context, criterion, value); - criterion.setValue(mappedValue); - } - } - } - } - } - - public void convertOrderBy(OrderBy orderBy) { - if (orderBy != null) { - List properties = orderBy.getProperties(); - properties = entityEle.toAliases(properties); - orderBy.setProperties(properties); - } - } - -} diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/impl/factory/OperationFactory.java b/dorive-core/src/main/java/com/gitee/dorive/core/impl/factory/OperationFactory.java index c2e7587c3e1b5e7a2b247f4476471e42c44d28c5..2d425c4d1d0b7f0e4edc4a49c5a3a496d15d33fa 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/impl/factory/OperationFactory.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/impl/factory/OperationFactory.java @@ -17,7 +17,6 @@ package com.gitee.dorive.core.impl.factory; -import com.gitee.dorive.api.constant.OperationType; import com.gitee.dorive.api.entity.element.EntityEle; import com.gitee.dorive.core.entity.executor.Example; import com.gitee.dorive.core.entity.operation.*; @@ -48,7 +47,7 @@ public class OperationFactory { public Update buildUpdate(Object entity) { Update update = new Update(entity); - Object primaryKey = entityEle.getPkProxy().getValue(entity); + Object primaryKey = entityEle.getIdProxy().getValue(entity); update.setPrimaryKey(primaryKey); return update; } @@ -60,7 +59,7 @@ public class OperationFactory { } public Operation buildInsertOrUpdate(Object entity) { - Object primaryKey = entityEle.getPkProxy().getValue(entity); + Object primaryKey = entityEle.getIdProxy().getValue(entity); if (primaryKey == null) { return new Insert(entity); } else { @@ -72,7 +71,7 @@ public class OperationFactory { public Delete buildDelete(Object entity) { Delete delete = new Delete(entity); - Object primaryKey = entityEle.getPkProxy().getValue(entity); + Object primaryKey = entityEle.getIdProxy().getValue(entity); delete.setPrimaryKey(primaryKey); return delete; } @@ -89,24 +88,4 @@ public class OperationFactory { return delete; } - public Operation renewOperation(Operation operation, Object entity) { - int type = operation.getType(); - if (type == OperationType.INSERT) { - return buildInsert(entity); - - } else if (type == OperationType.UPDATE) { - return buildUpdate(entity); - - } else if (type == OperationType.INSERT_OR_UPDATE) { - return new Operation(OperationType.INSERT_OR_UPDATE, entity); - - } else if (type == OperationType.DELETE) { - return buildDelete(entity); - - } else if (type == OperationType.FORCE_INSERT) { - return new Insert(OperationType.FORCE_INSERT, entity); - } - return null; - } - } diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/impl/handler/BatchEntityHandler.java b/dorive-core/src/main/java/com/gitee/dorive/core/impl/handler/BatchEntityHandler.java index dcf74e94a671a2109754c9791423a6377fbb1156..1c196901af30f6cc380e4d75777710ef37a69e63 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/impl/handler/BatchEntityHandler.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/impl/handler/BatchEntityHandler.java @@ -18,9 +18,16 @@ package com.gitee.dorive.core.impl.handler; import com.gitee.dorive.core.api.context.Context; -import com.gitee.dorive.core.api.context.Selector; import com.gitee.dorive.core.api.executor.EntityHandler; -import com.gitee.dorive.core.impl.resolver.BinderResolver; +import com.gitee.dorive.core.api.executor.EntityJoiner; +import com.gitee.dorive.core.entity.executor.Example; +import com.gitee.dorive.core.entity.executor.Result; +import com.gitee.dorive.core.entity.operation.Query; +import com.gitee.dorive.core.entity.option.JoinType; +import com.gitee.dorive.core.impl.factory.OperationFactory; +import com.gitee.dorive.core.impl.joiner.MultiEntityJoiner; +import com.gitee.dorive.core.impl.joiner.SingleEntityJoiner; +import com.gitee.dorive.core.impl.joiner.UnionEntityJoiner; import com.gitee.dorive.core.repository.AbstractContextRepository; import com.gitee.dorive.core.repository.CommonRepository; import lombok.AllArgsConstructor; @@ -36,17 +43,40 @@ public class BatchEntityHandler implements EntityHandler { @Override public long handle(Context context, List entities) { - Selector selector = context.getSelector(); long totalCount = 0L; for (CommonRepository repository : this.repository.getSubRepositories()) { - if (selector.matches(context, repository)) { - BinderResolver binderResolver = repository.getBinderResolver(); - EntityHandler entityHandler = binderResolver.isSimpleRootBinding() ? - new MultiEntityHandler(repository) : new UnionEntityHandler(repository); - totalCount += entityHandler.handle(context, entities); + if (repository.matches(context)) { + EntityJoiner entityJoiner = newEntityJoiner(repository, entities.size()); + if (entityJoiner == null) { + continue; + } + Example example = entityJoiner.newExample(context, entities); + if (example.isEmpty()) { + continue; + } + OperationFactory operationFactory = repository.getOperationFactory(); + Query query = operationFactory.buildQueryByExample(example); + query.includeRoot(); + Result result = repository.executeQuery(context, query); + entityJoiner.join(context, entities, result); + totalCount += result.getCount(); } } return totalCount; } + protected EntityJoiner newEntityJoiner(CommonRepository repository, int entitiesSize) { + JoinType joinType = repository.getJoinType(); + if (joinType == JoinType.SINGLE) { + return new SingleEntityJoiner(repository, entitiesSize); + + } else if (joinType == JoinType.MULTI) { + return new MultiEntityJoiner(repository, entitiesSize); + + } else if (joinType == JoinType.UNION) { + return new UnionEntityJoiner(repository, entitiesSize); + } + return null; + } + } diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/impl/handler/MultiEntityHandler.java b/dorive-core/src/main/java/com/gitee/dorive/core/impl/handler/MultiEntityHandler.java deleted file mode 100644 index 41b78610b07007baf66763f49939f070ce6636f7..0000000000000000000000000000000000000000 --- a/dorive-core/src/main/java/com/gitee/dorive/core/impl/handler/MultiEntityHandler.java +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.gitee.dorive.core.impl.handler; - -import com.gitee.dorive.api.entity.element.PropChain; -import com.gitee.dorive.core.api.context.Context; -import com.gitee.dorive.core.api.executor.EntityHandler; -import com.gitee.dorive.core.entity.executor.Example; -import com.gitee.dorive.core.entity.executor.InnerExample; -import com.gitee.dorive.core.entity.executor.MultiInBuilder; -import com.gitee.dorive.core.entity.executor.MultiResult; -import com.gitee.dorive.core.entity.executor.Result; -import com.gitee.dorive.core.entity.operation.Operation; -import com.gitee.dorive.core.entity.operation.Query; -import com.gitee.dorive.core.impl.binder.AbstractBinder; -import com.gitee.dorive.core.impl.binder.ContextBinder; -import com.gitee.dorive.core.impl.binder.PropertyBinder; -import com.gitee.dorive.core.impl.factory.OperationFactory; -import com.gitee.dorive.core.impl.resolver.BinderResolver; -import com.gitee.dorive.core.repository.CommonRepository; -import lombok.AllArgsConstructor; -import lombok.Data; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -@Data -@AllArgsConstructor -public class MultiEntityHandler implements EntityHandler { - - private final CommonRepository repository; - - @Override - public long handle(Context context, List entities) { - Map entityIndex = new LinkedHashMap<>(entities.size() * 4 / 3 + 1); - Example example = newExample(context, entities, entityIndex); - if (example.isNotEmpty()) { - OperationFactory operationFactory = repository.getOperationFactory(); - Query query = operationFactory.buildQueryByExample(example); - query.setRootType(Operation.INCLUDE_ROOT); - Result result = repository.executeQuery(context, query); - if (result instanceof MultiResult) { - setValueForRootEntities(context, entities, entityIndex, (MultiResult) result); - } - return result.getCount(); - } - return 0L; - } - - private Example newExample(Context context, List entities, Map entityIndex) { - BinderResolver binderResolver = repository.getBinderResolver(); - Map> mergedBindersMap = binderResolver.getMergedBindersMap(); - List binders = mergedBindersMap.get("/"); - - Example example = new InnerExample(); - if (binders.size() == 1) { - PropertyBinder binder = binders.get(0); - List boundValues = collectBoundValues(context, entities, entityIndex, binder); - if (!boundValues.isEmpty()) { - String fieldName = binder.getFieldName(); - if (boundValues.size() == 1) { - example.eq(fieldName, boundValues.get(0)); - } else { - example.in(fieldName, boundValues); - } - } - - } else { - List aliases = binders.stream().map(AbstractBinder::getAlias).collect(Collectors.toList()); - MultiInBuilder builder = new MultiInBuilder(entities.size(), aliases); - collectBoundValues(context, entities, entityIndex, binders, builder); - if (!builder.isEmpty()) { - example.getCriteria().add(builder.build()); - } - } - - if (example.isNotEmpty()) { - for (ContextBinder binder : binderResolver.getContextBinders()) { - String fieldName = binder.getFieldName(); - Object boundValue = binder.getBoundValue(context, null); - if (boundValue != null) { - example.eq(fieldName, boundValue); - } - } - } - - return example; - } - - private List collectBoundValues(Context context, List entities, Map entityIndex, PropertyBinder binder) { - List boundValues = new ArrayList<>(entities.size()); - for (Object entity : entities) { - Object boundValue = binder.getBoundValue(context, entity); - if (boundValue != null) { - boundValue = binder.input(context, boundValue); - String key = String.valueOf(boundValue); - if (!entityIndex.containsKey(key)) { - boundValues.add(boundValue); - } - addToIndex(entityIndex, key, entity); - } - } - return boundValues; - } - - private void collectBoundValues(Context context, List entities, Map entityIndex, List binders, - MultiInBuilder multiInBuilder) { - for (Object entity : entities) { - StringBuilder strBuilder = new StringBuilder(); - for (PropertyBinder binder : binders) { - Object boundValue = binder.getBoundValue(context, entity); - if (boundValue != null) { - boundValue = binder.input(context, boundValue); - multiInBuilder.append(boundValue); - String boundValueStr = String.valueOf(boundValue); - strBuilder.append("(").append(boundValueStr.length()).append(")").append(boundValueStr).append(","); - - } else { - multiInBuilder.clear(); - strBuilder = null; - break; - } - } - if (strBuilder != null) { - if (strBuilder.length() > 0) { - strBuilder.deleteCharAt(strBuilder.length() - 1); - } - String key = strBuilder.toString(); - if (entityIndex.containsKey(key)) { - multiInBuilder.clear(); - } - addToIndex(entityIndex, key, entity); - } - } - } - - @SuppressWarnings("unchecked") - private void addToIndex(Map entityIndex, String key, Object entity) { - Object object = entityIndex.get(key); - if (object instanceof Collection) { - ((Collection) object).add(entity); - - } else if (object != null) { - List entities = new ArrayList<>(4); - entities.add(object); - entities.add(entity); - entityIndex.put(key, entities); - - } else { - entityIndex.put(key, entity); - } - } - - @SuppressWarnings("unchecked") - private void setValueForRootEntities(Context context, List rootEntities, Map entityIndex, MultiResult multiResult) { - boolean isCollection = repository.getEntityEle().isCollection(); - PropChain anchorPoint = repository.getAnchorPoint(); - - BinderResolver binderResolver = repository.getBinderResolver(); - Map> mergedBindersMap = binderResolver.getMergedBindersMap(); - List binders = mergedBindersMap.get("/"); - - List entities = multiResult.getRecords(); - int averageSize = entities.size() / rootEntities.size() + 1; - - for (Object entity : entities) { - StringBuilder strBuilder = new StringBuilder(); - if (binders.size() == 1) { - PropertyBinder binder = binders.get(0); - Object fieldValue = binder.getFieldValue(context, entity); - if (fieldValue != null) { - strBuilder.append(fieldValue); - } else { - strBuilder = null; - } - } else { - for (PropertyBinder binder : binders) { - Object fieldValue = binder.getFieldValue(context, entity); - if (fieldValue != null) { - String fieldValueStr = String.valueOf(fieldValue); - strBuilder.append("(").append(fieldValueStr.length()).append(")").append(fieldValueStr).append(","); - - } else { - strBuilder = null; - break; - } - } - if (strBuilder != null && strBuilder.length() > 0) { - strBuilder.deleteCharAt(strBuilder.length() - 1); - } - } - if (strBuilder != null) { - Object object = entityIndex.get(strBuilder.toString()); - if (object instanceof Collection) { - for (Object rootEntity : (Collection) object) { - setValueForRootEntity(isCollection, anchorPoint, averageSize, rootEntity, entity); - } - } else { - setValueForRootEntity(isCollection, anchorPoint, averageSize, object, entity); - } - } - } - } - - @SuppressWarnings("unchecked") - private void setValueForRootEntity(boolean isCollection, PropChain anchorPoint, int averageSize, Object rootEntity, Object entity) { - if (rootEntity != null) { - Object value = anchorPoint.getValue(rootEntity); - if (isCollection) { - Collection collection; - if (value == null) { - collection = new ArrayList<>(averageSize); - anchorPoint.setValue(rootEntity, collection); - } else { - collection = (Collection) value; - } - collection.add(entity); - - } else { - if (value == null) { - anchorPoint.setValue(rootEntity, entity); - } - } - } - } - -} diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/impl/joiner/AbstractEntityJoiner.java b/dorive-core/src/main/java/com/gitee/dorive/core/impl/joiner/AbstractEntityJoiner.java new file mode 100644 index 0000000000000000000000000000000000000000..bbe7b8f995ec76a5d7f5f35af19dc06e87a32c18 --- /dev/null +++ b/dorive-core/src/main/java/com/gitee/dorive/core/impl/joiner/AbstractEntityJoiner.java @@ -0,0 +1,121 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.gitee.dorive.core.impl.joiner; + +import com.gitee.dorive.api.entity.element.PropChain; +import com.gitee.dorive.core.api.context.Context; +import com.gitee.dorive.core.api.executor.EntityJoiner; +import com.gitee.dorive.core.entity.executor.Example; +import com.gitee.dorive.core.entity.executor.Result; +import com.gitee.dorive.core.impl.binder.ContextBinder; +import com.gitee.dorive.core.impl.resolver.BinderResolver; +import com.gitee.dorive.core.repository.CommonRepository; +import org.apache.commons.lang3.StringUtils; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public abstract class AbstractEntityJoiner implements EntityJoiner { + + protected CommonRepository repository; + protected Map rootIndex; + protected Set keys; + protected Map recordIndex; + protected int averageSize; + + public AbstractEntityJoiner(CommonRepository repository, int entitiesSize) { + this.repository = repository; + int size = entitiesSize * 4 / 3 + 1; + this.rootIndex = new LinkedHashMap<>(size); + this.keys = new LinkedHashSet<>(size); + this.recordIndex = new LinkedHashMap<>(size); + } + + protected void appendContext(Context context, Example example) { + if (example == null || example.isEmpty()) { + return; + } + BinderResolver binderResolver = repository.getBinderResolver(); + List contextBinders = binderResolver.getContextBinders(); + for (ContextBinder contextBinder : contextBinders) { + Object boundValue = contextBinder.getBoundValue(context, null); + if (boundValue != null) { + String fieldName = contextBinder.getFieldName(); + example.eq(fieldName, boundValue); + } + } + } + + protected void addToRootIndex(Object entity, String key) { + if (entity == null || StringUtils.isBlank(key)) { + return; + } + rootIndex.put(System.identityHashCode(entity), key); + keys.add(key); + } + + @Override + public void join(Context context, List entities, Result result) { + List records = result.getRecords(); + averageSize = records.size() / entities.size() + 1; + buildRecordIndex(context, entities, result); + joinMany(entities); + } + + @SuppressWarnings("unchecked") + protected void addToRecordIndex(String key, Object entity) { + if (StringUtils.isBlank(key) || entity == null) { + return; + } + if (repository.isCollection()) { + Collection collection = (Collection) recordIndex.computeIfAbsent(key, k -> new ArrayList<>(averageSize)); + collection.add(entity); + } else { + recordIndex.putIfAbsent(key, entity); + } + } + + protected void joinMany(List entities) { + for (Object entity : entities) { + String key = rootIndex.get(System.identityHashCode(entity)); + if (key != null) { + Object object = recordIndex.get(key); + joinOne(entity, object); + } + } + } + + protected void joinOne(Object entity, Object object) { + if (entity == null || object == null) { + return; + } + PropChain anchorPoint = repository.getAnchorPoint(); + Object value = anchorPoint.getValue(entity); + if (value == null) { + anchorPoint.setValue(entity, object); + } + } + + protected abstract void buildRecordIndex(Context context, List entities, Result result); + +} diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/impl/joiner/MultiEntityJoiner.java b/dorive-core/src/main/java/com/gitee/dorive/core/impl/joiner/MultiEntityJoiner.java new file mode 100644 index 0000000000000000000000000000000000000000..5f2d66fa933b98e6757ee4e414e52a32c4ed6695 --- /dev/null +++ b/dorive-core/src/main/java/com/gitee/dorive/core/impl/joiner/MultiEntityJoiner.java @@ -0,0 +1,113 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.gitee.dorive.core.impl.joiner; + +import com.gitee.dorive.core.api.context.Context; +import com.gitee.dorive.core.entity.executor.Example; +import com.gitee.dorive.core.entity.executor.InnerExample; +import com.gitee.dorive.core.entity.executor.Result; +import com.gitee.dorive.core.impl.binder.AbstractBinder; +import com.gitee.dorive.core.impl.binder.PropertyBinder; +import com.gitee.dorive.core.repository.CommonRepository; +import com.gitee.dorive.core.util.MultiInBuilder; +import lombok.Getter; +import lombok.Setter; + +import java.util.List; +import java.util.stream.Collectors; + +@Getter +@Setter +public class MultiEntityJoiner extends AbstractEntityJoiner { + + private List binders; + + public MultiEntityJoiner(CommonRepository repository, int entitiesSize) { + super(repository, entitiesSize); + this.binders = repository.getRootBinders(); + } + + @Override + public Example newExample(Context context, List entities) { + Example example = new InnerExample(); + MultiInBuilder builder = newMultiInBuilder(context, entities); + if (!builder.isEmpty()) { + example.getCriteria().add(builder.toCriterion()); + } + appendContext(context, example); + return example; + } + + private MultiInBuilder newMultiInBuilder(Context context, List entities) { + List aliases = binders.stream().map(AbstractBinder::getAlias).collect(Collectors.toList()); + MultiInBuilder multiInBuilder = new MultiInBuilder(aliases, entities.size()); + + for (Object entity : entities) { + StringBuilder keyBuilder = new StringBuilder(); + for (PropertyBinder binder : binders) { + Object boundValue = binder.getBoundValue(context, entity); + if (boundValue != null) { + boundValue = binder.input(context, boundValue); + } + if (boundValue != null) { + multiInBuilder.append(boundValue); + String key = boundValue.toString(); + keyBuilder.append("(").append(key.length()).append(")").append(key).append(","); + } else { + multiInBuilder.clearRemainder(); + keyBuilder = null; + break; + } + } + if (keyBuilder != null && keyBuilder.length() > 0) { + keyBuilder.deleteCharAt(keyBuilder.length() - 1); + String key = keyBuilder.toString(); + if (keys.contains(key)) { + multiInBuilder.clearLast(); + } + addToRootIndex(entity, key); + } + } + + return multiInBuilder; + } + + @Override + protected void buildRecordIndex(Context context, List entities, Result result) { + List records = result.getRecords(); + for (Object entity : records) { + StringBuilder keyBuilder = new StringBuilder(); + for (PropertyBinder binder : binders) { + Object fieldValue = binder.getFieldValue(context, entity); + if (fieldValue != null) { + String key = fieldValue.toString(); + keyBuilder.append("(").append(key.length()).append(")").append(key).append(","); + } else { + keyBuilder = null; + break; + } + } + if (keyBuilder != null && keyBuilder.length() > 0) { + keyBuilder.deleteCharAt(keyBuilder.length() - 1); + String key = keyBuilder.toString(); + addToRecordIndex(key, entity); + } + } + } + +} diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/impl/handler/AdaptiveEntityHandler.java b/dorive-core/src/main/java/com/gitee/dorive/core/impl/joiner/SingleEntityJoiner.java similarity index 31% rename from dorive-core/src/main/java/com/gitee/dorive/core/impl/handler/AdaptiveEntityHandler.java rename to dorive-core/src/main/java/com/gitee/dorive/core/impl/joiner/SingleEntityJoiner.java index 618241e4867b342e951ef270faa98442757a2f04..166f981eb43553eec313c5183c50ca84584a58ca 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/impl/handler/AdaptiveEntityHandler.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/impl/joiner/SingleEntityJoiner.java @@ -15,67 +15,75 @@ * limitations under the License. */ -package com.gitee.dorive.core.impl.handler; +package com.gitee.dorive.core.impl.joiner; import com.gitee.dorive.core.api.context.Context; -import com.gitee.dorive.core.api.executor.EntityHandler; -import com.gitee.dorive.core.api.executor.Executor; -import com.gitee.dorive.core.impl.resolver.DerivedResolver; -import com.gitee.dorive.core.repository.AbstractContextRepository; -import lombok.Data; +import com.gitee.dorive.core.entity.executor.Example; +import com.gitee.dorive.core.entity.executor.InnerExample; +import com.gitee.dorive.core.entity.executor.Result; +import com.gitee.dorive.core.impl.binder.PropertyBinder; +import com.gitee.dorive.core.repository.CommonRepository; +import lombok.Getter; +import lombok.Setter; import java.util.ArrayList; -import java.util.LinkedHashMap; import java.util.List; -import java.util.Map; -@Data -public class AdaptiveEntityHandler implements EntityHandler { +@Getter +@Setter +public class SingleEntityJoiner extends AbstractEntityJoiner { - private final AbstractContextRepository repository; - private final EntityHandler entityHandler; + private PropertyBinder binder; - public AdaptiveEntityHandler(AbstractContextRepository repository, EntityHandler entityHandler) { - this.repository = repository; - this.entityHandler = entityHandler; + public SingleEntityJoiner(CommonRepository repository, int entitiesSize) { + super(repository, entitiesSize); + this.binder = repository.getRootBinders().get(0); } @Override - public long handle(Context context, List entities) { - List newEntities = new ArrayList<>(entities.size()); - Map, List> repositoryEntitiesMap = distribute(entities, newEntities); - - long totalCount = 0L; - if (!newEntities.isEmpty()) { - totalCount += (entityHandler.handle(context, newEntities)); - } - for (Map.Entry, List> entry : repositoryEntitiesMap.entrySet()) { - AbstractContextRepository repository = entry.getKey(); - List subclassEntities = entry.getValue(); - Executor executor = repository.getExecutor(); - if (executor instanceof EntityHandler) { - totalCount += (((EntityHandler) executor).handle(context, subclassEntities)); + public Example newExample(Context context, List entities) { + Example example = new InnerExample(); + List boundValues = collectBoundValues(context, entities); + if (!boundValues.isEmpty()) { + String fieldName = binder.getFieldName(); + if (boundValues.size() == 1) { + example.eq(fieldName, boundValues.get(0)); + } else { + example.in(fieldName, boundValues); } } - return totalCount; + appendContext(context, example); + return example; } - private Map, List> distribute(List entities, List newEntities) { - DerivedResolver derivedResolver = repository.getDerivedResolver(); - int numberOf = derivedResolver.numberOf(); - Map, List> repositoryEntitiesMap = new LinkedHashMap<>(numberOf * 4 / 3 + 1); - + private List collectBoundValues(Context context, List entities) { + List boundValues = new ArrayList<>(entities.size()); for (Object entity : entities) { - AbstractContextRepository repository = derivedResolver.deriveRepository(entity); - if (repository == null) { - newEntities.add(entity); - } else { - List existEntities = repositoryEntitiesMap.computeIfAbsent(repository, key -> new ArrayList<>(entities.size())); - existEntities.add(entity); + Object boundValue = binder.getBoundValue(context, entity); + if (boundValue != null) { + boundValue = binder.input(context, boundValue); + } + if (boundValue != null) { + String key = boundValue.toString(); + if (!keys.contains(key)) { + boundValues.add(boundValue); + } + addToRootIndex(entity, key); } } + return boundValues; + } - return repositoryEntitiesMap; + @Override + protected void buildRecordIndex(Context context, List entities, Result result) { + List records = result.getRecords(); + for (Object entity : records) { + Object fieldValue = binder.getFieldValue(context, entity); + if (fieldValue != null) { + String key = fieldValue.toString(); + addToRecordIndex(key, entity); + } + } } } diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/impl/handler/UnionEntityHandler.java b/dorive-core/src/main/java/com/gitee/dorive/core/impl/joiner/UnionEntityJoiner.java similarity index 41% rename from dorive-core/src/main/java/com/gitee/dorive/core/impl/handler/UnionEntityHandler.java rename to dorive-core/src/main/java/com/gitee/dorive/core/impl/joiner/UnionEntityJoiner.java index 9de37af0b001b46b5a4b452905c4e9e71a80ac48..9a46330febd931b2e3293da0a1df8afb6d4d6461 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/impl/handler/UnionEntityHandler.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/impl/joiner/UnionEntityJoiner.java @@ -15,132 +15,96 @@ * limitations under the License. */ -package com.gitee.dorive.core.impl.handler; +package com.gitee.dorive.core.impl.joiner; import com.gitee.dorive.api.entity.element.PropChain; import com.gitee.dorive.core.api.context.Context; -import com.gitee.dorive.core.api.executor.EntityHandler; import com.gitee.dorive.core.entity.executor.Example; import com.gitee.dorive.core.entity.executor.InnerExample; -import com.gitee.dorive.core.entity.executor.MultiResult; import com.gitee.dorive.core.entity.executor.Result; import com.gitee.dorive.core.entity.executor.UnionExample; -import com.gitee.dorive.core.entity.operation.Operation; -import com.gitee.dorive.core.entity.operation.Query; -import com.gitee.dorive.core.impl.binder.ContextBinder; import com.gitee.dorive.core.impl.binder.PropertyBinder; -import com.gitee.dorive.core.impl.factory.OperationFactory; -import com.gitee.dorive.core.impl.resolver.BinderResolver; import com.gitee.dorive.core.repository.CommonRepository; -import com.gitee.dorive.core.util.NumberUtils; -import lombok.AllArgsConstructor; -import lombok.Data; +import lombok.Getter; +import lombok.Setter; -import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; -@Data -@AllArgsConstructor -public class UnionEntityHandler implements EntityHandler { +@Getter +@Setter +public class UnionEntityJoiner extends AbstractEntityJoiner { - private final CommonRepository repository; - - @Override - public long handle(Context context, List entities) { - Example example = newExample(context, entities); - if (example.isNotEmpty()) { - OperationFactory operationFactory = repository.getOperationFactory(); - Query query = operationFactory.buildQueryByExample(example); - query.setRootType(Operation.INCLUDE_ROOT); - Result result = repository.executeQuery(context, query); - if (result instanceof MultiResult) { - setValueForRootEntities(entities, (MultiResult) result); - } - return result.getCount(); - } - return 0L; + public UnionEntityJoiner(CommonRepository repository, int entitiesSize) { + super(repository, entitiesSize); } - private Example newExample(Context context, List entities) { + @Override + public Example newExample(Context context, List entities) { PropChain anchorPoint = repository.getAnchorPoint(); PropChain lastPropChain = anchorPoint.getLastPropChain(); UnionExample unionExample = new UnionExample(); for (int index = 0; index < entities.size(); index++) { Object entity = entities.get(index); Object lastEntity = lastPropChain == null ? entity : lastPropChain.getValue(entity); - if (lastEntity != null) { - Example example = newExample(context, entity); - if (example.isNotEmpty()) { - example.selectExtra((index + 1) + " as $row"); - unionExample.addExample(example); - } + if (lastEntity == null) { + continue; } + Example example = newExample(context, entity); + if (example.isEmpty()) { + continue; + } + String row = Integer.toString(index + 1); + example.setSelectSuffix(row + " as $row"); + unionExample.addExample(example); + addToRootIndex(entity, row); } return unionExample; } private Example newExample(Context context, Object entity) { - BinderResolver binderResolver = repository.getBinderResolver(); Example example = new InnerExample(); - for (PropertyBinder binder : binderResolver.getPropertyBinders()) { - String fieldName = binder.getFieldName(); + List binders = repository.getBinderResolver().getPropertyBinders(); + for (PropertyBinder binder : binders) { Object boundValue = binder.getBoundValue(context, entity); if (boundValue instanceof Collection) { - boundValue = !((Collection) boundValue).isEmpty() ? boundValue : null; + if (((Collection) boundValue).isEmpty()) { + boundValue = null; + } } if (boundValue != null) { boundValue = binder.input(context, boundValue); + } + if (boundValue != null) { + String fieldName = binder.getFieldName(); example.eq(fieldName, boundValue); } else { example.getCriteria().clear(); break; } } - if (example.isNotEmpty()) { - for (ContextBinder binder : binderResolver.getContextBinders()) { - String fieldName = binder.getFieldName(); - Object boundValue = binder.getBoundValue(context, entity); - if (boundValue != null) { - example.eq(fieldName, boundValue); - } - } - } + appendContext(context, example); return example; } - private void setValueForRootEntities(List rootEntities, MultiResult multiResult) { - boolean isCollection = repository.getEntityEle().isCollection(); - PropChain anchorPoint = repository.getAnchorPoint(); - - List> resultMaps = multiResult.getResultMaps(); - int averageSize = resultMaps.size() / rootEntities.size() + 1; - int lastRowNum = -1; - Collection lastCollection = null; - - for (Map resultMap : resultMaps) { - Integer rowNum = NumberUtils.intValue(resultMap.get("$row")); + @Override + @SuppressWarnings("unchecked") + protected void buildRecordIndex(Context context, List entities, Result result) { + List> recordMaps = result.getRecordMaps(); + for (Map resultMap : recordMaps) { + Object row = resultMap.get("$row"); + List rows = (List) resultMap.get("$rows"); Object entity = resultMap.get("$entity"); - - if (rowNum == lastRowNum) { - if (isCollection && lastCollection != null) { - lastCollection.add(entity); - } - - } else { - Object rootEntity = rootEntities.get(rowNum - 1); - if (isCollection) { - Collection collection = new ArrayList<>(averageSize); - collection.add(entity); - lastCollection = collection; - anchorPoint.setValue(rootEntity, collection); - } else { - anchorPoint.setValue(rootEntity, entity); + if (entity != null) { + if (rows != null) { + for (String eachRow : rows) { + addToRecordIndex(eachRow, entity); + } + } else if (row != null) { + addToRecordIndex(row.toString(), entity); } } - - lastRowNum = rowNum; } } diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/impl/processor/DefaultBindingProcessor.java b/dorive-core/src/main/java/com/gitee/dorive/core/impl/processor/DefaultProcessor.java similarity index 91% rename from dorive-core/src/main/java/com/gitee/dorive/core/impl/processor/DefaultBindingProcessor.java rename to dorive-core/src/main/java/com/gitee/dorive/core/impl/processor/DefaultProcessor.java index bc38046a6a31e8f02fd769a8d17ad3adbf29d040..69d1381ad826a6d09550955489af7a90cf87c63b 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/impl/processor/DefaultBindingProcessor.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/impl/processor/DefaultProcessor.java @@ -18,14 +18,14 @@ package com.gitee.dorive.core.impl.processor; import com.gitee.dorive.api.entity.def.BindingDef; -import com.gitee.dorive.core.api.binder.BindingProcessor; +import com.gitee.dorive.core.api.binder.Processor; import com.gitee.dorive.core.api.context.Context; import lombok.Data; import lombok.NoArgsConstructor; @Data @NoArgsConstructor -public class DefaultBindingProcessor implements BindingProcessor { +public class DefaultProcessor implements Processor { private BindingDef bindingDef; diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/impl/processor/PropertyBindingProcessor.java b/dorive-core/src/main/java/com/gitee/dorive/core/impl/processor/PropertyProcessor.java similarity index 95% rename from dorive-core/src/main/java/com/gitee/dorive/core/impl/processor/PropertyBindingProcessor.java rename to dorive-core/src/main/java/com/gitee/dorive/core/impl/processor/PropertyProcessor.java index 139190f979ba46692a47f368e7274b986feecc4d..0bdb69e0f9dab56f25f2ef1627b42d8cea54cfc7 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/impl/processor/PropertyBindingProcessor.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/impl/processor/PropertyProcessor.java @@ -27,7 +27,7 @@ import java.util.Collection; @Data @EqualsAndHashCode(callSuper = false) -public class PropertyBindingProcessor extends DefaultBindingProcessor { +public class PropertyProcessor extends DefaultProcessor { @Override public Object input(Context context, Object value) { diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/impl/resolver/BinderResolver.java b/dorive-core/src/main/java/com/gitee/dorive/core/impl/resolver/BinderResolver.java index 08d2fdbbf1243cb7e54cc89098af155924f21fd6..4298bf01ff166ac141b5ff8c1d1bc91304e2c313 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/impl/resolver/BinderResolver.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/impl/resolver/BinderResolver.java @@ -27,11 +27,12 @@ import com.gitee.dorive.api.entity.element.EntityEle; import com.gitee.dorive.api.entity.element.PropChain; import com.gitee.dorive.api.impl.resolver.PropChainResolver; import com.gitee.dorive.core.api.binder.Binder; -import com.gitee.dorive.core.api.binder.BindingProcessor; +import com.gitee.dorive.core.api.binder.Processor; +import com.gitee.dorive.core.entity.option.JoinType; import com.gitee.dorive.core.impl.binder.ContextBinder; import com.gitee.dorive.core.impl.binder.PropertyBinder; -import com.gitee.dorive.core.impl.processor.DefaultBindingProcessor; -import com.gitee.dorive.core.impl.processor.PropertyBindingProcessor; +import com.gitee.dorive.core.impl.processor.DefaultProcessor; +import com.gitee.dorive.core.impl.processor.PropertyProcessor; import com.gitee.dorive.core.repository.AbstractContextRepository; import com.gitee.dorive.core.repository.CommonRepository; import com.gitee.dorive.core.util.PathUtils; @@ -54,7 +55,7 @@ public class BinderResolver { private List allBinders; private List propertyBinders; private Map> mergedBindersMap; - private boolean simpleRootBinding; + private JoinType joinType; private List selfFields; private List contextBinders; private List boundValueBinders; @@ -67,12 +68,15 @@ public class BinderResolver { public void resolve(String accessPath, EntityDef entityDef, EntityEle entityEle) { Map propChainMap = propChainResolver.getPropChainMap(); + + Class genericType = entityEle.getGenericType(); + String idName = entityEle.getIdName(); List bindingDefs = entityEle.getBindingDefs(); allBinders = new ArrayList<>(bindingDefs.size()); propertyBinders = new ArrayList<>(bindingDefs.size()); mergedBindersMap = new LinkedHashMap<>(bindingDefs.size() * 4 / 3 + 1); - simpleRootBinding = false; + joinType = JoinType.UNKNOWN; selfFields = new ArrayList<>(bindingDefs.size()); contextBinders = new ArrayList<>(bindingDefs.size()); boundValueBinders = new ArrayList<>(bindingDefs.size()); @@ -87,13 +91,13 @@ public class BinderResolver { PropChain fieldPropChain = propChainMap.get("/" + field); Assert.notNull(fieldPropChain, "The field configured for @Binding does not exist within the entity! type: {}, field: {}", - entityEle.getGenericType().getName(), field); + genericType.getName(), field); fieldPropChain.newPropProxy(); - BindingProcessor bindingProcessor = newBindingProcessor(bindingDef); + Processor processor = newProcessor(bindingDef); if (bindExp.startsWith("/")) { - PropertyBinder propertyBinder = newPropertyBinder(bindingDef, alias, fieldPropChain, bindingProcessor); + PropertyBinder propertyBinder = newPropertyBinder(bindingDef, alias, fieldPropChain, processor); allBinders.add(propertyBinder); propertyBinders.add(propertyBinder); @@ -104,7 +108,7 @@ public class BinderResolver { selfFields.add(field); if (propertyBinder.isSameType()) { - if (!"id".equals(field)) { + if (!idName.equals(field)) { boundValueBinders.add(propertyBinder); } else { if (entityDef.getPriority() == 0) { @@ -115,7 +119,7 @@ public class BinderResolver { } } else { - ContextBinder contextBinder = new ContextBinder(bindingDef, alias, fieldPropChain, bindingProcessor); + ContextBinder contextBinder = new ContextBinder(bindingDef, alias, fieldPropChain, processor); allBinders.add(contextBinder); contextBinders.add(contextBinder); boundValueBinders.add(contextBinder); @@ -123,7 +127,14 @@ public class BinderResolver { } if (mergedBindersMap.size() == 1 && mergedBindersMap.containsKey("/")) { - simpleRootBinding = CollUtil.findOne(mergedBindersMap.get("/"), PropertyBinder::isCollection) == null; + List binders = mergedBindersMap.get("/"); + boolean hasCollection = CollUtil.findOne(binders, PropertyBinder::isCollection) != null; + if (!hasCollection) { + joinType = binders.size() == 1 ? JoinType.SINGLE : JoinType.MULTI; + } + } + if (joinType == JoinType.UNKNOWN) { + joinType = JoinType.UNION; } selfFields = Collections.unmodifiableList(selfFields); } @@ -138,37 +149,37 @@ public class BinderResolver { return bindingDef; } - private BindingProcessor newBindingProcessor(BindingDef bindingDef) { + private Processor newProcessor(BindingDef bindingDef) { Assert.notNull(bindingDef, "The bindingDef cannot be null!"); Class processorClass = bindingDef.getProcessor(); - BindingProcessor bindingProcessor = null; + Processor processor = null; if (processorClass == Object.class) { if (StringUtils.isBlank(bindingDef.getProperty())) { - bindingProcessor = new DefaultBindingProcessor(); + processor = new DefaultProcessor(); } else { - bindingProcessor = new PropertyBindingProcessor(); + processor = new PropertyProcessor(); } } else { ApplicationContext applicationContext = repository.getApplicationContext(); String[] beanNamesForType = applicationContext.getBeanNamesForType(processorClass); if (beanNamesForType.length > 0) { - bindingProcessor = (BindingProcessor) applicationContext.getBean(beanNamesForType[0]); + processor = (Processor) applicationContext.getBean(beanNamesForType[0]); } - if (bindingProcessor == null) { - bindingProcessor = (BindingProcessor) ReflectUtil.newInstance(processorClass); + if (processor == null) { + processor = (Processor) ReflectUtil.newInstance(processorClass); } } - if (bindingProcessor instanceof DefaultBindingProcessor) { - DefaultBindingProcessor defaultProcessor = (DefaultBindingProcessor) bindingProcessor; + if (processor instanceof DefaultProcessor) { + DefaultProcessor defaultProcessor = (DefaultProcessor) processor; defaultProcessor.setBindingDef(bindingDef); } - if (bindingProcessor instanceof PropertyBindingProcessor) { - Assert.notBlank(bindingDef.getProperty(), "The property of PropertyBindingProcessor cannot be blank!"); + if (processor instanceof PropertyProcessor) { + Assert.notBlank(bindingDef.getProperty(), "The property of PropertyProcessor cannot be blank!"); } - return bindingProcessor; + return processor; } - private PropertyBinder newPropertyBinder(BindingDef bindingDef, String alias, PropChain fieldPropChain, BindingProcessor bindingProcessor) { + private PropertyBinder newPropertyBinder(BindingDef bindingDef, String alias, PropChain fieldPropChain, Processor processor) { String bindExp = bindingDef.getBindExp(); String property = bindingDef.getProperty(); @@ -188,7 +199,7 @@ public class BinderResolver { String boundName = StringUtils.isBlank(property) ? PathUtils.getLastName(bindExp) : property; String bindAlias = entityEle.toAlias(boundName); - return new PropertyBinder(bindingDef, alias, fieldPropChain, bindingProcessor, + return new PropertyBinder(bindingDef, alias, fieldPropChain, processor, belongAccessPath, belongRepository, boundPropChain, bindAlias); } diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/impl/resolver/DerivedResolver.java b/dorive-core/src/main/java/com/gitee/dorive/core/impl/resolver/DerivedResolver.java index 95cce01c586518387fac26c0739fd82f4ff40ad3..4a788e29968642a248da10d9f8766d7996efc5be 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/impl/resolver/DerivedResolver.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/impl/resolver/DerivedResolver.java @@ -22,21 +22,23 @@ import lombok.Data; import org.springframework.context.ApplicationContext; import org.springframework.util.ReflectionUtils; +import java.util.ArrayList; import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; @Data public class DerivedResolver { private AbstractContextRepository repository; - private Map, AbstractContextRepository> derivedRepositoryMap = new LinkedHashMap<>(3 * 4 / 3 + 1); + private Map, AbstractContextRepository> classRepositoryMap = new LinkedHashMap<>(3 * 4 / 3 + 1); public DerivedResolver(AbstractContextRepository repository) { this.repository = repository; resolve(); } - public void resolve() { + private void resolve() { ReflectionUtils.doWithLocalFields(repository.getClass(), declaredField -> { Class fieldClass = declaredField.getType(); if (AbstractContextRepository.class.isAssignableFrom(fieldClass)) { @@ -45,22 +47,29 @@ public class DerivedResolver { AbstractContextRepository abstractContextRepository = (AbstractContextRepository) beanInstance; Class fieldEntityClass = abstractContextRepository.getEntityClass(); if (repository.getEntityClass().isAssignableFrom(fieldEntityClass)) { - derivedRepositoryMap.put(fieldEntityClass, abstractContextRepository); + classRepositoryMap.put(fieldEntityClass, abstractContextRepository); } } }); } - public boolean isDerived() { - return !derivedRepositoryMap.isEmpty(); + public boolean hasDerived() { + return !classRepositoryMap.isEmpty(); } - public int numberOf() { - return derivedRepositoryMap.size(); + public AbstractContextRepository distribute(Object entity) { + return classRepositoryMap.getOrDefault(entity.getClass(), repository); } - public AbstractContextRepository deriveRepository(Object entity) { - return derivedRepositoryMap.get(entity.getClass()); + public Map, List> distribute(List entities) { + int size = classRepositoryMap.size() + 1; + Map, List> repositoryEntitiesMap = new LinkedHashMap<>(size * 4 / 3 + 1); + for (Object entity : entities) { + AbstractContextRepository repository = distribute(entity); + List existEntities = repositoryEntitiesMap.computeIfAbsent(repository, key -> new ArrayList<>(entities.size())); + existEntities.add(entity); + } + return repositoryEntitiesMap; } } diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/impl/resolver/EntityMapperResolver.java b/dorive-core/src/main/java/com/gitee/dorive/core/impl/resolver/EntityMapperResolver.java new file mode 100644 index 0000000000000000000000000000000000000000..056bbb3339b78ffe0b630993e4d4701a22d2f0b9 --- /dev/null +++ b/dorive-core/src/main/java/com/gitee/dorive/core/impl/resolver/EntityMapperResolver.java @@ -0,0 +1,117 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.gitee.dorive.core.impl.resolver; + +import cn.hutool.core.util.ReflectUtil; +import com.gitee.dorive.api.entity.def.FieldDef; +import com.gitee.dorive.api.entity.element.EntityEle; +import com.gitee.dorive.api.entity.element.EntityField; +import com.gitee.dorive.core.api.converter.Converter; +import com.gitee.dorive.core.api.converter.EntityMapper; +import com.gitee.dorive.core.entity.common.EntityStoreInfo; +import com.gitee.dorive.core.impl.converter.DefaultConverter; +import com.gitee.dorive.core.impl.converter.DefaultEntityMapper; +import lombok.AllArgsConstructor; +import lombok.Data; +import org.apache.commons.lang3.StringUtils; + +import java.util.LinkedHashMap; +import java.util.Map; + +@Data +@AllArgsConstructor +public class EntityMapperResolver { + + private EntityEle entityEle; + private EntityStoreInfo entityStoreInfo; + + public EntityMapper resolve() { + Map fieldAliasMapping = entityEle.getFieldAliasMapping(); + Map aliasFieldMapping = newAliasFieldMapping(fieldAliasMapping); + Map fieldPropMapping = newFieldPropMapping(aliasFieldMapping); + + Map fieldConverterMap = newFieldConverterMap(); + Map aliasConverterMap = newAliasConverterMap(fieldAliasMapping, fieldConverterMap); + Map propConverterMap = newPropConverterMap(fieldPropMapping, fieldConverterMap); + + return new DefaultEntityMapper(fieldAliasMapping, aliasFieldMapping, fieldPropMapping, + fieldConverterMap, aliasConverterMap, propConverterMap); + } + + private Map newAliasFieldMapping(Map fieldAliasMapping) { + Map aliasFieldMapping = new LinkedHashMap<>(); + fieldAliasMapping.forEach((field, alias) -> aliasFieldMapping.put(alias, field)); + return aliasFieldMapping; + } + + private Map newFieldPropMapping(Map aliasFieldMapping) { + Map fieldPropMapping = new LinkedHashMap<>(); + Map propAliasMapping = entityStoreInfo.getPropAliasMapping(); + propAliasMapping.forEach((prop, alias) -> { + String field = aliasFieldMapping.get(alias); + if (field != null) { + fieldPropMapping.put(field, prop); + } + }); + return fieldPropMapping; + } + + private Map newFieldConverterMap() { + Map fieldConverterMap = new LinkedHashMap<>(8); + Map entityFieldMap = entityEle.getEntityFieldMap(); + if (entityFieldMap != null) { + entityFieldMap.forEach((field, entityField) -> { + FieldDef fieldDef = entityField.getFieldDef(); + if (fieldDef != null) { + Class converterClass = fieldDef.getConverter(); + String mapExp = fieldDef.getMapExp(); + Converter converter = null; + if (converterClass != Object.class) { + converter = (Converter) ReflectUtil.newInstance(converterClass); + + } else if (StringUtils.isNotBlank(mapExp)) { + converter = new DefaultConverter(entityField); + } + if (converter != null) { + fieldConverterMap.put(field, converter); + } + } + }); + } + return fieldConverterMap; + } + + private Map newAliasConverterMap(Map fieldAliasMapping, Map fieldConverterMap) { + Map aliasConverterMap = new LinkedHashMap<>(fieldConverterMap.size()); + fieldConverterMap.forEach((field, converter) -> { + String alias = fieldAliasMapping.get(field); + aliasConverterMap.put(alias, converter); + }); + return aliasConverterMap; + } + + private Map newPropConverterMap(Map fieldPropMapping, Map fieldConverterMap) { + Map propConverterMap = new LinkedHashMap<>(fieldConverterMap.size()); + fieldConverterMap.forEach((field, converter) -> { + String prop = fieldPropMapping.get(field); + propConverterMap.put(prop, converter); + }); + return propConverterMap; + } + +} diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/impl/selector/RootSelector.java b/dorive-core/src/main/java/com/gitee/dorive/core/impl/selector/RootSelector.java deleted file mode 100644 index 041c68144a3b2e47b7a5169ce6e580340617cef4..0000000000000000000000000000000000000000 --- a/dorive-core/src/main/java/com/gitee/dorive/core/impl/selector/RootSelector.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.gitee.dorive.core.impl.selector; - -import com.gitee.dorive.core.api.context.Context; -import com.gitee.dorive.core.api.context.Node; -import lombok.Data; -import lombok.EqualsAndHashCode; - -@Data -@EqualsAndHashCode(callSuper = false) -public class RootSelector extends AbstractSelector { - - @Override - public boolean matches(Context context, Node node) { - return node.isRoot(); - } - -} diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/repository/AbstractContextRepository.java b/dorive-core/src/main/java/com/gitee/dorive/core/repository/AbstractContextRepository.java index 63cd0367fe27000c7ec7dfa534c4b6add29814e3..8ccee70b1bf771ab0832b516f0015623bd8ffcab 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/repository/AbstractContextRepository.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/repository/AbstractContextRepository.java @@ -19,36 +19,33 @@ package com.gitee.dorive.core.repository; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.lang.Assert; -import cn.hutool.core.util.ReflectUtil; import cn.hutool.core.util.StrUtil; -import com.gitee.dorive.api.constant.Keys; import com.gitee.dorive.api.constant.Order; import com.gitee.dorive.api.entity.def.EntityDef; -import com.gitee.dorive.api.entity.def.FieldDef; import com.gitee.dorive.api.entity.element.EntityEle; -import com.gitee.dorive.api.entity.element.EntityField; import com.gitee.dorive.api.entity.element.EntityType; import com.gitee.dorive.api.entity.element.PropChain; import com.gitee.dorive.api.impl.resolver.PropChainResolver; import com.gitee.dorive.api.util.ReflectUtils; -import com.gitee.dorive.core.api.executor.EntityFactory; +import com.gitee.dorive.core.api.converter.EntityFactory; +import com.gitee.dorive.core.api.converter.EntityMapper; import com.gitee.dorive.core.api.executor.EntityHandler; import com.gitee.dorive.core.api.executor.Executor; -import com.gitee.dorive.core.api.executor.FieldConverter; import com.gitee.dorive.core.config.RepositoryContext; -import com.gitee.dorive.core.entity.ExecutorResult; +import com.gitee.dorive.core.entity.common.EntityStoreInfo; import com.gitee.dorive.core.entity.executor.OrderBy; -import com.gitee.dorive.core.impl.converter.DefaultFieldConverter; -import com.gitee.dorive.core.impl.executor.DefaultExecutor; +import com.gitee.dorive.core.impl.context.SelectTypeMatcher; +import com.gitee.dorive.core.impl.converter.DefaultEntityFactory; +import com.gitee.dorive.core.impl.executor.ContextExecutor; +import com.gitee.dorive.core.impl.executor.ExampleExecutor; import com.gitee.dorive.core.impl.executor.FactoryExecutor; -import com.gitee.dorive.core.impl.executor.FieldExecutor; import com.gitee.dorive.core.impl.factory.OperationFactory; -import com.gitee.dorive.core.impl.handler.AdaptiveEntityHandler; import com.gitee.dorive.core.impl.handler.BatchEntityHandler; import com.gitee.dorive.core.impl.resolver.BinderResolver; import com.gitee.dorive.core.impl.resolver.DerivedResolver; -import lombok.Data; -import lombok.EqualsAndHashCode; +import com.gitee.dorive.core.impl.resolver.EntityMapperResolver; +import lombok.Getter; +import lombok.Setter; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.BeansException; import org.springframework.beans.factory.InitializingBean; @@ -62,10 +59,13 @@ import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; -@Data -@EqualsAndHashCode(callSuper = false) +@Getter +@Setter public abstract class AbstractContextRepository extends AbstractRepository implements ApplicationContextAware, InitializingBean { + private static final Map ENTITY_STORE_INFO_MAP = new ConcurrentHashMap<>(); + private static final Map EXAMPLE_EXECUTOR_MAP = new ConcurrentHashMap<>(); + private ApplicationContext applicationContext; private PropChainResolver propChainResolver; @@ -76,6 +76,14 @@ public abstract class AbstractContextRepository extends AbstractRepositor private List subRepositories = new ArrayList<>(); private List orderedRepositories = new ArrayList<>(); + public static EntityStoreInfo getEntityStoreInfo(EntityEle entityEle) { + return ENTITY_STORE_INFO_MAP.get(entityEle); + } + + public static ExampleExecutor getExampleExecutor(EntityEle entityEle) { + return EXAMPLE_EXECUTOR_MAP.get(entityEle); + } + @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; @@ -109,8 +117,12 @@ public abstract class AbstractContextRepository extends AbstractRepositor setEntityDef(rootRepository.getEntityDef()); setEntityEle(rootRepository.getEntityEle()); setOperationFactory(rootRepository.getOperationFactory()); - setExecutor(newDefaultExecutor()); - setAttachments(new ConcurrentHashMap<>(rootRepository.getAttachments())); + + derivedResolver = new DerivedResolver(this); + + EntityHandler entityHandler = processEntityHandler(new BatchEntityHandler(this)); + Executor executor = new ContextExecutor(this, entityHandler); + setExecutor(executor); } private CommonRepository newRepository(String accessPath, EntityEle entityEle) { @@ -135,7 +147,6 @@ public abstract class AbstractContextRepository extends AbstractRepositor repository.setEntityEle(entityEle); repository.setOperationFactory(operationFactory); repository.setProxyRepository(proxyRepository); - repository.setAttachments(new ConcurrentHashMap<>(actualRepository.getAttachments())); repository.setAccessPath(accessPath); repository.setRoot(isRoot); @@ -145,7 +156,7 @@ public abstract class AbstractContextRepository extends AbstractRepositor repository.setAnchorPoint(anchorPoint); repository.setBinderResolver(binderResolver); repository.setBoundEntity(false); - + repository.setMatcher(new SelectTypeMatcher(repository)); return repository; } @@ -176,46 +187,36 @@ public abstract class AbstractContextRepository extends AbstractRepositor defaultRepository.setEntityEle(entityEle); defaultRepository.setOperationFactory(operationFactory); - Map converterMap = newConverterMap(entityEle); - Map attachments = new ConcurrentHashMap<>(8); - - ExecutorResult executorResult = newExecutor(entityDef, entityEle, converterMap, attachments); - EntityFactory entityFactory = executorResult.getEntityFactory(); - Executor executor = executorResult.getExecutor(); + EntityStoreInfo entityStoreInfo = resolveEntityStoreInfo(entityDef, entityEle); + ENTITY_STORE_INFO_MAP.put(entityEle, entityStoreInfo); - executor = new FactoryExecutor(executor, entityEle, entityFactory); - executor = new FieldExecutor(executor, entityEle, converterMap); - attachments.put(Keys.FIELD_EXECUTOR, executor); + EntityMapper entityMapper = new EntityMapperResolver(entityEle, entityStoreInfo).resolve(); + EntityFactory entityFactory = newEntityFactory(entityDef, entityEle, entityStoreInfo, entityMapper); + Executor executor = newExecutor(entityDef, entityEle, entityStoreInfo); + executor = new FactoryExecutor(executor, entityEle, entityStoreInfo, entityFactory); + executor = new ExampleExecutor(executor, entityEle, entityMapper); + EXAMPLE_EXECUTOR_MAP.put(entityEle, (ExampleExecutor) executor); defaultRepository.setExecutor(executor); - defaultRepository.setAttachments(attachments); } return (AbstractRepository) repository; } - private Map newConverterMap(EntityEle entityEle) { - Map converterMap = new LinkedHashMap<>(8); - Map entityFieldMap = entityEle.getEntityFieldMap(); - if (entityFieldMap != null) { - entityFieldMap.forEach((name, entityField) -> { - FieldDef fieldDef = entityField.getFieldDef(); - if (fieldDef != null) { - Class converterClass = fieldDef.getConverter(); - String mapExp = fieldDef.getMapExp(); - FieldConverter fieldConverter = null; - if (converterClass != Object.class) { - fieldConverter = (FieldConverter) ReflectUtil.newInstance(converterClass); - - } else if (StringUtils.isNotBlank(mapExp)) { - fieldConverter = new DefaultFieldConverter(entityField); - } - if (fieldConverter != null) { - converterMap.put(name, fieldConverter); - } - } - }); + private EntityFactory newEntityFactory(EntityDef entityDef, EntityEle entityEle, EntityStoreInfo entityStoreInfo, EntityMapper entityMapper) { + Class factoryClass = entityDef.getFactory(); + EntityFactory entityFactory; + if (factoryClass == Object.class) { + entityFactory = new DefaultEntityFactory(); + } else { + entityFactory = (EntityFactory) applicationContext.getBean(factoryClass); + } + if (entityFactory instanceof DefaultEntityFactory) { + DefaultEntityFactory defaultEntityFactory = (DefaultEntityFactory) entityFactory; + defaultEntityFactory.setEntityEle(entityEle); + defaultEntityFactory.setEntityStoreInfo(entityStoreInfo); + defaultEntityFactory.setEntityMapper(entityMapper); } - return converterMap; + return entityFactory; } private OrderBy newDefaultOrderBy(EntityDef entityDef) { @@ -228,16 +229,9 @@ public abstract class AbstractContextRepository extends AbstractRepositor return null; } - private Executor newDefaultExecutor() { - EntityHandler entityHandler = processEntityHandler(new BatchEntityHandler(this)); - derivedResolver = new DerivedResolver(this); - if (derivedResolver.isDerived()) { - entityHandler = new AdaptiveEntityHandler(this, entityHandler); - } - return new DefaultExecutor(this, entityHandler); - } + protected abstract EntityStoreInfo resolveEntityStoreInfo(EntityDef entityDef, EntityEle entityEle); - protected abstract ExecutorResult newExecutor(EntityDef entityDef, EntityEle entityEle, Map converterMap, Map attachments); + protected abstract Executor newExecutor(EntityDef entityDef, EntityEle entityEle, EntityStoreInfo entityStoreInfo); protected abstract AbstractRepository processRepository(AbstractRepository repository); diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/repository/AbstractGenericRepository.java b/dorive-core/src/main/java/com/gitee/dorive/core/repository/AbstractGenericRepository.java index d2feb79995d3b97c05e00b720f04f9e92d7c764b..a8480cb4903dc5866df978350b0542085f7ad943 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/repository/AbstractGenericRepository.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/repository/AbstractGenericRepository.java @@ -18,88 +18,82 @@ package com.gitee.dorive.core.repository; import cn.hutool.core.lang.Assert; -import com.gitee.dorive.api.constant.OperationType; import com.gitee.dorive.core.api.context.Context; -import com.gitee.dorive.core.api.context.Selector; +import com.gitee.dorive.core.api.context.Options; import com.gitee.dorive.core.api.repository.ListableRepository; import com.gitee.dorive.core.entity.executor.Example; +import com.gitee.dorive.core.entity.operation.InsertOrUpdate; import com.gitee.dorive.core.entity.operation.Operation; import com.gitee.dorive.core.util.ExampleUtils; -import lombok.Data; -import lombok.EqualsAndHashCode; import java.util.List; -@Data -@EqualsAndHashCode(callSuper = false) public abstract class AbstractGenericRepository extends AbstractContextRepository implements ListableRepository { @Override - public long selectCount(Context context, Example example) { + public long selectCountByExample(Options options, Example example) { Assert.notNull(example, "The example cannot be null!"); CommonRepository repository = getRootRepository(); - return repository.selectCount(context, example); + return repository.selectCountByExample(options, example); } @Override - public int updateByExample(Context context, Object entity, Example example) { + public int updateByExample(Options options, Object entity, Example example) { Assert.notNull(entity, "The entity cannot be null!"); Assert.notNull(example, "The example cannot be null!"); - Selector selector = context.getSelector(); int totalCount = 0; for (CommonRepository repository : getOrderedRepositories()) { - if (selector.matches(context, repository)) { - totalCount += repository.updateByExample(context, entity, ExampleUtils.tryClone(example)); + if (repository.matches((Context) options)) { + totalCount += repository.updateByExample(options, entity, ExampleUtils.clone(example)); } } return totalCount; } @Override - public int insertOrUpdate(Context context, E entity) { + public int insertOrUpdate(Options options, E entity) { Assert.notNull(entity, "The entity cannot be null!"); - Operation operation = new Operation(OperationType.INSERT_OR_UPDATE, entity); - return execute(context, operation); + Operation operation = new InsertOrUpdate(entity); + return execute((Context) options, operation); } @Override - public int deleteByPrimaryKey(Context context, PK primaryKey) { + public int deleteByPrimaryKey(Options options, PK primaryKey) { Assert.notNull(primaryKey, "The primary key cannot be null!"); - E entity = selectByPrimaryKey(context, primaryKey); - return delete(context, entity); + E entity = selectByPrimaryKey(options, primaryKey); + return delete(options, entity); } @Override - public int deleteByExample(Context context, Example example) { + public int deleteByExample(Options options, Example example) { Assert.notNull(example, "The example cannot be null!"); - Selector selector = context.getSelector(); int totalCount = 0; for (CommonRepository repository : getOrderedRepositories()) { - if (selector.matches(context, repository)) { - totalCount += repository.deleteByExample(context, ExampleUtils.tryClone(example)); + if (repository.matches((Context) options)) { + totalCount += repository.deleteByExample(options, ExampleUtils.clone(example)); } } return totalCount; } @Override - public int insertList(Context context, List entities) { - return entities.stream().mapToInt(entity -> insert(context, entity)).sum(); + public int insertList(Options options, List entities) { + return entities.stream().mapToInt(entity -> insert(options, entity)).sum(); } @Override - public int updateList(Context context, List entities) { - return entities.stream().mapToInt(entity -> update(context, entity)).sum(); + public int updateList(Options options, List entities) { + return entities.stream().mapToInt(entity -> update(options, entity)).sum(); } @Override - public int insertOrUpdateList(Context context, List entities) { - return entities.stream().mapToInt(entity -> insertOrUpdate(context, entity)).sum(); + public int insertOrUpdateList(Options options, List entities) { + return entities.stream().mapToInt(entity -> insertOrUpdate(options, entity)).sum(); } @Override - public int deleteList(Context context, List entities) { - return entities.stream().mapToInt(entity -> delete(context, entity)).sum(); + public int deleteList(Options options, List entities) { + return entities.stream().mapToInt(entity -> delete(options, entity)).sum(); } } diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/repository/AbstractProxyRepository.java b/dorive-core/src/main/java/com/gitee/dorive/core/repository/AbstractProxyRepository.java index b13b22a7f0eb1e24be1cc208226d3ab536981d97..f13a3b5e808a1584f278e288a64c8c0b86fb135b 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/repository/AbstractProxyRepository.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/repository/AbstractProxyRepository.java @@ -18,22 +18,23 @@ package com.gitee.dorive.core.repository; import com.gitee.dorive.core.api.context.Context; +import com.gitee.dorive.core.api.context.Options; import com.gitee.dorive.core.entity.executor.Example; import com.gitee.dorive.core.entity.executor.Page; import com.gitee.dorive.core.entity.executor.Result; import com.gitee.dorive.core.entity.operation.Operation; import com.gitee.dorive.core.entity.operation.Query; import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.EqualsAndHashCode; +import lombok.Getter; import lombok.NoArgsConstructor; +import lombok.Setter; import java.util.List; -@Data +@Getter +@Setter @NoArgsConstructor @AllArgsConstructor -@EqualsAndHashCode(callSuper = false) public abstract class AbstractProxyRepository extends AbstractRepository { private AbstractRepository proxyRepository; @@ -53,58 +54,58 @@ public abstract class AbstractProxyRepository extends AbstractRepository selectByExample(Context context, Example example) { - return proxyRepository.selectByExample(context, example); + public List selectByExample(Options options, Example example) { + return proxyRepository.selectByExample(options, example); } @Override - public Page selectPageByExample(Context context, Example example) { - return proxyRepository.selectPageByExample(context, example); + public Page selectPageByExample(Options options, Example example) { + return proxyRepository.selectPageByExample(options, example); } @Override - public long selectCount(Context context, Example example) { - return proxyRepository.selectCount(context, example); + public long selectCountByExample(Options options, Example example) { + return proxyRepository.selectCountByExample(options, example); } @Override - public int insert(Context context, Object entity) { - return proxyRepository.insert(context, entity); + public int insert(Options options, Object entity) { + return proxyRepository.insert(options, entity); } @Override - public int update(Context context, Object entity) { - return proxyRepository.update(context, entity); + public int update(Options options, Object entity) { + return proxyRepository.update(options, entity); } @Override - public int updateByExample(Context context, Object entity, Example example) { - return proxyRepository.updateByExample(context, entity, example); + public int updateByExample(Options options, Object entity, Example example) { + return proxyRepository.updateByExample(options, entity, example); } @Override - public int insertOrUpdate(Context context, Object entity) { - return proxyRepository.insertOrUpdate(context, entity); + public int insertOrUpdate(Options options, Object entity) { + return proxyRepository.insertOrUpdate(options, entity); } @Override - public int delete(Context context, Object entity) { - return proxyRepository.delete(context, entity); + public int delete(Options options, Object entity) { + return proxyRepository.delete(options, entity); } @Override - public int deleteByPrimaryKey(Context context, Object primaryKey) { - return proxyRepository.deleteByPrimaryKey(context, primaryKey); + public int deleteByPrimaryKey(Options options, Object primaryKey) { + return proxyRepository.deleteByPrimaryKey(options, primaryKey); } @Override - public int deleteByExample(Context context, Example example) { - return proxyRepository.deleteByExample(context, example); + public int deleteByExample(Options options, Example example) { + return proxyRepository.deleteByExample(options, example); } @Override diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/repository/AbstractRepository.java b/dorive-core/src/main/java/com/gitee/dorive/core/repository/AbstractRepository.java index 34697b8b8bd4006454d7440110b6f2932a1f867b..fa6c1c9c09f4b15b52154dc28e0827a0e7207cea 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/repository/AbstractRepository.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/repository/AbstractRepository.java @@ -21,6 +21,7 @@ import cn.hutool.core.lang.Assert; import com.gitee.dorive.api.entity.def.EntityDef; import com.gitee.dorive.api.entity.element.EntityEle; import com.gitee.dorive.core.api.context.Context; +import com.gitee.dorive.core.api.context.Options; import com.gitee.dorive.core.api.executor.Executor; import com.gitee.dorive.core.api.repository.Repository; import com.gitee.dorive.core.entity.executor.Example; @@ -32,19 +33,19 @@ import com.gitee.dorive.core.entity.operation.Operation; import com.gitee.dorive.core.entity.operation.Query; import com.gitee.dorive.core.entity.operation.Update; import com.gitee.dorive.core.impl.factory.OperationFactory; -import lombok.Data; +import lombok.Getter; +import lombok.Setter; import java.util.List; -import java.util.Map; -@Data +@Getter +@Setter public abstract class AbstractRepository implements Repository, Executor { private EntityDef entityDef; private EntityEle entityEle; private OperationFactory operationFactory; private Executor executor; - private Map attachments; public Class getEntityClass() { return entityEle.getGenericType(); @@ -52,87 +53,93 @@ public abstract class AbstractRepository implements Repository, Ex @Override @SuppressWarnings("unchecked") - public E selectByPrimaryKey(Context context, PK primaryKey) { + public E selectByPrimaryKey(Options options, PK primaryKey) { Assert.notNull(primaryKey, "The primary key cannot be null!"); Query query = operationFactory.buildQueryByPK(primaryKey); - Result result = executeQuery(context, query); + Result result = executeQuery((Context) options, query); return (E) result.getRecord(); } @Override @SuppressWarnings("unchecked") - public List selectByExample(Context context, Example example) { + public List selectByExample(Options options, Example example) { Assert.notNull(example, "The example cannot be null!"); Query query = operationFactory.buildQueryByExample(example); - Result result = executeQuery(context, query); + Result result = executeQuery((Context) options, query); return (List) result.getRecords(); } + @Override + public E selectOneByExample(Options options, Example example) { + List entities = selectByExample(options, example); + return entities != null && !entities.isEmpty() ? entities.get(0) : null; + } + @Override @SuppressWarnings("unchecked") - public Page selectPageByExample(Context context, Example example) { + public Page selectPageByExample(Options options, Example example) { Assert.notNull(example, "The example cannot be null!"); Assert.notNull(example.getPage(), "The page cannot be null!"); Query query = operationFactory.buildQueryByExample(example); - Result result = executeQuery(context, query); + Result result = executeQuery((Context) options, query); return (Page) result.getPage(); } @Override - public long selectCount(Context context, Example example) { + public long selectCountByExample(Options options, Example example) { Assert.notNull(example, "The example cannot be null!"); Query query = operationFactory.buildQueryByExample(example); - return executeCount(context, query); + return executeCount((Context) options, query); } @Override - public int insert(Context context, E entity) { + public int insert(Options options, E entity) { Assert.notNull(entity, "The entity cannot be null!"); Insert insert = operationFactory.buildInsert(entity); - return execute(context, insert); + return execute((Context) options, insert); } @Override - public int update(Context context, E entity) { + public int update(Options options, E entity) { Assert.notNull(entity, "The entity cannot be null!"); Update update = operationFactory.buildUpdate(entity); - return execute(context, update); + return execute((Context) options, update); } @Override - public int updateByExample(Context context, Object entity, Example example) { + public int updateByExample(Options options, Object entity, Example example) { Assert.notNull(entity, "The entity cannot be null!"); Assert.notNull(example, "The example cannot be null!"); Update update = operationFactory.buildUpdateByExample(entity, example); - return execute(context, update); + return execute((Context) options, update); } @Override - public int insertOrUpdate(Context context, E entity) { + public int insertOrUpdate(Options options, E entity) { Assert.notNull(entity, "The entity cannot be null!"); Operation operation = operationFactory.buildInsertOrUpdate(entity); - return execute(context, operation); + return execute((Context) options, operation); } @Override - public int delete(Context context, E entity) { + public int delete(Options options, E entity) { Assert.notNull(entity, "The entity cannot be null!"); Delete delete = operationFactory.buildDelete(entity); - return execute(context, delete); + return execute((Context) options, delete); } @Override - public int deleteByPrimaryKey(Context context, PK primaryKey) { + public int deleteByPrimaryKey(Options options, PK primaryKey) { Assert.notNull(primaryKey, "The primary key cannot be null!"); Delete delete = operationFactory.buildDeleteByPK(primaryKey); - return execute(context, delete); + return execute((Context) options, delete); } @Override - public int deleteByExample(Context context, Example example) { + public int deleteByExample(Options options, Example example) { Assert.notNull(example, "The example cannot be null!"); Delete delete = operationFactory.buildDeleteByExample(example); - return execute(context, delete); + return execute((Context) options, delete); } @Override diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/repository/CommonRepository.java b/dorive-core/src/main/java/com/gitee/dorive/core/repository/CommonRepository.java index fd51b1db081024439e7b841aff1b586b2df72468..458272a04d493cafdd911705891ab8d55999dc31 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/repository/CommonRepository.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/repository/CommonRepository.java @@ -19,22 +19,25 @@ package com.gitee.dorive.core.repository; import com.gitee.dorive.api.entity.element.PropChain; import com.gitee.dorive.core.api.context.Context; -import com.gitee.dorive.core.api.context.Node; +import com.gitee.dorive.core.api.context.Matcher; import com.gitee.dorive.core.api.context.Selector; import com.gitee.dorive.core.entity.executor.Example; import com.gitee.dorive.core.entity.executor.InnerExample; import com.gitee.dorive.core.entity.executor.OrderBy; import com.gitee.dorive.core.entity.executor.Result; import com.gitee.dorive.core.entity.operation.Query; +import com.gitee.dorive.core.entity.option.JoinType; +import com.gitee.dorive.core.impl.binder.PropertyBinder; import com.gitee.dorive.core.impl.resolver.BinderResolver; -import lombok.Data; -import lombok.EqualsAndHashCode; +import com.gitee.dorive.core.util.ExampleUtils; +import lombok.Getter; +import lombok.Setter; import java.util.List; -@Data -@EqualsAndHashCode(callSuper = false) -public class CommonRepository extends AbstractProxyRepository implements Node { +@Getter +@Setter +public class CommonRepository extends AbstractProxyRepository implements Matcher { private String accessPath; private boolean root; @@ -43,39 +46,59 @@ public class CommonRepository extends AbstractProxyRepository implements Node { private PropChain anchorPoint; private BinderResolver binderResolver; private boolean boundEntity; + private Matcher matcher; + + public String getName() { + return getEntityDef().getName(); + } + + public boolean isCollection() { + return getEntityEle().isCollection(); + } public Object getPrimaryKey(Object entity) { - return getEntityEle().getPkProxy().getValue(entity); + return getEntityEle().getIdProxy().getValue(entity); } public boolean hasField(String field) { return getEntityEle().hasField(field); } + public JoinType getJoinType() { + return binderResolver.getJoinType(); + } + + public List getRootBinders() { + return binderResolver.getMergedBindersMap().get("/"); + } + @Override - public String getName() { - return getEntityDef().getName(); + public boolean matches(Context context) { + return matcher.matches(context); } @Override public Result executeQuery(Context context, Query query) { - Selector selector = context.getSelector(); - List properties = selector.select(context, this); - if (properties != null && !properties.isEmpty()) { - if (query.getPrimaryKey() != null) { - Example example = new InnerExample().eq("id", query.getPrimaryKey()); - query.setPrimaryKey(null); - query.setExample(example); - } - Example example = query.getExample(); - if (example != null) { - example.select(properties); + Selector selector = (Selector) context.getOption(Selector.class); + if (selector != null) { + List properties = selector.select(getName()); + if (properties != null && !properties.isEmpty()) { + Object primaryKey = query.getPrimaryKey(); + if (primaryKey != null) { + Example example = new InnerExample().eq(getEntityEle().getIdName(), primaryKey); + query.setPrimaryKey(null); + query.setExample(example); + } + Example example = query.getExample(); + if (example != null) { + example.select(properties); + } } } Example example = query.getExample(); if (example != null) { if (example.getOrderBy() == null && defaultOrderBy != null) { - example.setOrderBy(defaultOrderBy.tryClone()); + example.setOrderBy(ExampleUtils.clone(defaultOrderBy)); } } return super.executeQuery(context, query); diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/repository/DefaultRepository.java b/dorive-core/src/main/java/com/gitee/dorive/core/repository/DefaultRepository.java index ec576f8ac08a16b34b1b8407ec667839cb6c030c..0309eae3e9f95c2023ba709a981d70e241fe9f6e 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/repository/DefaultRepository.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/repository/DefaultRepository.java @@ -17,12 +17,12 @@ package com.gitee.dorive.core.repository; -import lombok.Data; -import lombok.EqualsAndHashCode; +import lombok.Getter; import lombok.NoArgsConstructor; +import lombok.Setter; -@Data +@Getter +@Setter @NoArgsConstructor -@EqualsAndHashCode(callSuper = false) public class DefaultRepository extends AbstractRepository { } diff --git a/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/util/SqlUtils.java b/dorive-core/src/main/java/com/gitee/dorive/core/util/CollectionUtils.java similarity index 66% rename from dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/util/SqlUtils.java rename to dorive-core/src/main/java/com/gitee/dorive/core/util/CollectionUtils.java index e9f23486b30c0c64bed4db3bb8c222f9adece07b..7ae8769267619d45182898f1be2a1970372b2af8 100644 --- a/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/util/SqlUtils.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/util/CollectionUtils.java @@ -15,18 +15,21 @@ * limitations under the License. */ -package com.gitee.dorive.spring.boot.starter.util; +package com.gitee.dorive.core.util; -public class SqlUtils { +import java.util.Collection; +import java.util.Collections; - public static Object toLike(Object value) { - if (value instanceof String) { - String valueStr = (String) value; - if (!valueStr.startsWith("%") && !valueStr.endsWith("%")) { - return "%" + valueStr + "%"; - } +public class CollectionUtils { + + public static Collection toCollection(Object object) { + Collection collection; + if (object instanceof Collection) { + collection = (Collection) object; + } else { + collection = Collections.singletonList(object); } - return value; + return collection; } } diff --git a/dorive-coating/src/main/java/com/gitee/dorive/coating/api/ExampleBuilder.java b/dorive-core/src/main/java/com/gitee/dorive/core/util/ContextUtils.java similarity index 79% rename from dorive-coating/src/main/java/com/gitee/dorive/coating/api/ExampleBuilder.java rename to dorive-core/src/main/java/com/gitee/dorive/core/util/ContextUtils.java index 350ebf7233f45dbd08fbfe1b8e66f47075a02065..8df9b305d8baea2d4f33613efdc85f6e51d34e09 100644 --- a/dorive-coating/src/main/java/com/gitee/dorive/coating/api/ExampleBuilder.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/util/ContextUtils.java @@ -15,13 +15,15 @@ * limitations under the License. */ -package com.gitee.dorive.coating.api; +package com.gitee.dorive.core.util; -import com.gitee.dorive.coating.entity.BuildExample; import com.gitee.dorive.core.api.context.Context; +import com.gitee.dorive.core.entity.context.InnerContext; -public interface ExampleBuilder { +public class ContextUtils { - BuildExample buildExample(Context context, Object coating); + public static Context clone(Context context) { + return new InnerContext(context); + } } diff --git a/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/util/CriterionUtils.java b/dorive-core/src/main/java/com/gitee/dorive/core/util/CriterionUtils.java similarity index 76% rename from dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/util/CriterionUtils.java rename to dorive-core/src/main/java/com/gitee/dorive/core/util/CriterionUtils.java index f3dba511e463b81b3b6674ea55ed5d3926624ded..6b6b2350f2e1a8259ff1d3c7a0cd9f65bb4db578 100644 --- a/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/util/CriterionUtils.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/util/CriterionUtils.java @@ -15,11 +15,13 @@ * limitations under the License. */ -package com.gitee.dorive.spring.boot.starter.util; +package com.gitee.dorive.core.util; import cn.hutool.core.date.DateUtil; -import com.baomidou.mybatisplus.core.toolkit.StringUtils; +import cn.hutool.extra.spring.SpringUtil; +import com.gitee.dorive.api.api.ImplFactory; import com.gitee.dorive.api.constant.Operator; +import com.gitee.dorive.core.api.format.SqlFormat; import com.gitee.dorive.core.entity.executor.Criterion; import java.util.Collection; @@ -27,6 +29,13 @@ import java.util.Date; public class CriterionUtils { + private static final SqlFormat sqlFormat; + + static { + ImplFactory implFactory = SpringUtil.getBean(ImplFactory.class); + sqlFormat = implFactory.getInstance(SqlFormat.class); + } + public static String getOperator(Criterion criterion) { String operator = criterion.getOperator(); Object value = criterion.getValue(); @@ -43,18 +52,20 @@ public class CriterionUtils { } else if (Operator.NOT_IN.equals(operator)) { operator = Operator.NE; - - } else if (Operator.NULL_SWITCH.equals(operator) && value instanceof Boolean) { - return (Boolean) value ? Operator.IS_NULL : Operator.IS_NOT_NULL; } } return operator; } - public static Object getValue(Criterion criterion) { + public static String getValue(Criterion criterion) { String operator = criterion.getOperator(); Object value = criterion.getValue(); - return StringUtils.sqlParam(format(operator, value)); + return doGetValue(operator, value); + } + + public static String doGetValue(String operator, Object value) { + value = format(operator, value); + return sqlParam(value); } public static Object format(String operator, Object value) { @@ -65,11 +76,15 @@ public class CriterionUtils { value = DateUtil.formatDateTime((Date) value); } if (Operator.LIKE.equals(operator) || Operator.NOT_LIKE.equals(operator)) { - value = SqlUtils.toLike(value); + value = sqlFormat.concatLike(value); } return value; } + public static String sqlParam(Object obj) { + return sqlFormat.sqlParam(obj); + } + public static String toString(Criterion criterion) { String property = criterion.getProperty(); String operator = getOperator(criterion); diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/util/ExampleUtils.java b/dorive-core/src/main/java/com/gitee/dorive/core/util/ExampleUtils.java index bc6382f21590d66d8edb9f11b196635aca20db94..67c97e2013a560697497f7c81828bf42f0d6f5bd 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/util/ExampleUtils.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/util/ExampleUtils.java @@ -28,7 +28,7 @@ import java.util.List; public class ExampleUtils { - public static Example tryClone(Example example) { + public static Example clone(Example example) { if (example == null) { return null; } @@ -39,30 +39,42 @@ public class ExampleUtils { newExample.select(new ArrayList<>(selectProps)); } - List extraProps = example.getExtraProps(); - if (extraProps != null) { - newExample.selectExtra(new ArrayList<>(extraProps)); + String selectSuffix = example.getSelectSuffix(); + if (selectSuffix != null) { + newExample.setSelectSuffix(selectSuffix); } List criteria = example.getCriteria(); if (criteria != null && !criteria.isEmpty()) { List newCriteria = newExample.getCriteria(); for (Criterion criterion : criteria) { - newCriteria.add(criterion.tryClone()); + newCriteria.add(clone(criterion)); } } OrderBy orderBy = example.getOrderBy(); if (orderBy != null) { - newExample.setOrderBy(orderBy.tryClone()); + newExample.setOrderBy(clone(orderBy)); } Page page = example.getPage(); if (page != null) { - newExample.setPage(page.tryClone()); + newExample.setPage(clone(page)); } return newExample; } + public static Criterion clone(Criterion criterion) { + return new Criterion(criterion.getProperty(), criterion.getOperator(), criterion.getValue()); + } + + public static OrderBy clone(OrderBy orderBy) { + return new OrderBy(new ArrayList<>(orderBy.getProperties()), orderBy.getOrder()); + } + + public static Page clone(Page page) { + return new Page<>(page.getTotal(), page.getCurrent(), page.getSize(), new ArrayList<>(page.getRecords())); + } + } diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/entity/executor/MultiInBuilder.java b/dorive-core/src/main/java/com/gitee/dorive/core/util/MultiInBuilder.java similarity index 48% rename from dorive-core/src/main/java/com/gitee/dorive/core/entity/executor/MultiInBuilder.java rename to dorive-core/src/main/java/com/gitee/dorive/core/util/MultiInBuilder.java index 1bf01dbe852da096b0ccb60fa1beb7a1ea999e4f..57ed1af780c87d78977ce5420b24ffe96ce79da9 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/entity/executor/MultiInBuilder.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/util/MultiInBuilder.java @@ -15,62 +15,74 @@ * limitations under the License. */ -package com.gitee.dorive.core.entity.executor; +package com.gitee.dorive.core.util; import cn.hutool.core.util.StrUtil; import com.gitee.dorive.api.constant.Operator; +import com.gitee.dorive.core.entity.executor.Criterion; import lombok.Data; import lombok.EqualsAndHashCode; import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; @Data @EqualsAndHashCode(callSuper = false) public class MultiInBuilder { - private int size; private List aliases; - private int step; + private int size; + private int count; private List values; - private int cursor; - public MultiInBuilder(int size, List aliases) { - this.size = size; + public MultiInBuilder(List aliases, int count) { this.aliases = aliases; - this.step = aliases.size(); - this.values = new ArrayList<>(size * step); - this.cursor = 0; + this.size = aliases.size(); + this.count = count; + this.values = new ArrayList<>(count * size); } - public void append(Object value) { - if (values.size() - cursor >= step) { - cursor += step; - } - values.add(value); + public boolean isEmpty() { + return values.isEmpty(); } - public void clear() { - values.subList(cursor, values.size()).clear(); + public void append(Object value) { + values.add(value); } - public boolean isEmpty() { - return values.isEmpty(); + public void clearRemainder() { + int total = values.size(); + int remainder = total % size; + if (remainder != 0) { + values.subList(total - remainder, total).clear(); + } } - public int page() { - return values.size() / step; + public void clearLast() { + int total = values.size(); + int remainder = total % size; + if (remainder == 0) { + values.subList(total - size, total).clear(); + } } - public List get(int page) { - int fromIndex = (page - 1) * step; - int toIndex = fromIndex + step; - return values.subList(fromIndex, toIndex); + public Criterion toCriterion() { + String property = StrUtil.join(",", aliases); + StringBuilder builder = new StringBuilder(); + int page = values.size() / size; + for (int current = 1; current <= page; current++) { + List subValues = values.subList((current - 1) * size, current * size); + builder.append(buildValuesStr(subValues)); + } + String valuesStr = StrUtil.removeSuffix(builder, ","); + return new Criterion(property, Operator.MULTI_IN, valuesStr); } - public Criterion build() { - String aliasesStr = StrUtil.join(",", aliases); - return new Criterion(aliasesStr, Operator.MULTI_IN, this); + public String buildValuesStr(List values) { + return values.stream() + .map(value -> CriterionUtils.doGetValue(null, value)) + .collect(Collectors.joining(",", "(", "),")); } } diff --git a/dorive-env/pom.xml b/dorive-env/pom.xml index a6204db1f33e8002216a5ee50ea1979168a1d118..16060c10b7e9cd67e8c2c1f9f6a35015c43cbac9 100644 --- a/dorive-env/pom.xml +++ b/dorive-env/pom.xml @@ -6,7 +6,7 @@ com.gitee.digital-engine dorive - 3.4.3.1 + 3.4.3.3 dorive-env diff --git a/dorive-event/pom.xml b/dorive-event/pom.xml index c2072bd2b5dab437b135fd123addd1faa05b02c5..42a09b4c3a0544584d07b5b5941514c7c8418e7e 100644 --- a/dorive-event/pom.xml +++ b/dorive-event/pom.xml @@ -6,7 +6,7 @@ com.gitee.digital-engine dorive - 3.4.3.1 + 3.4.3.3 dorive-event @@ -15,5 +15,9 @@ dorive-core ${project.version} + + org.springframework + spring-tx + \ No newline at end of file diff --git a/dorive-event/src/main/java/com/gitee/dorive/event/annotation/EntityListener.java b/dorive-event/src/main/java/com/gitee/dorive/event/annotation/EntityListener.java new file mode 100644 index 0000000000000000000000000000000000000000..249fae23da6f72623ba7034686ea928b42f1b473 --- /dev/null +++ b/dorive-event/src/main/java/com/gitee/dorive/event/annotation/EntityListener.java @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.gitee.dorive.event.annotation; + +import com.gitee.dorive.event.entity.OperationType; +import org.springframework.stereotype.Component; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import static com.gitee.dorive.event.entity.OperationType.DELETE; +import static com.gitee.dorive.event.entity.OperationType.INSERT; +import static com.gitee.dorive.event.entity.OperationType.UPDATE; + +@Component +@Inherited +@Documented +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface EntityListener { + + Class value(); + + OperationType[] subscribeTo() default {INSERT, UPDATE, DELETE}; + + boolean afterCommit() default false; + + Class[] rollbackFor() default {}; + +} diff --git a/dorive-event/src/main/java/com/gitee/dorive/event/api/EntityEventListener.java b/dorive-event/src/main/java/com/gitee/dorive/event/api/EntityEventListener.java new file mode 100644 index 0000000000000000000000000000000000000000..fb6116ce69fe3922c8e2bb57ecbf38aa1d0171fd --- /dev/null +++ b/dorive-event/src/main/java/com/gitee/dorive/event/api/EntityEventListener.java @@ -0,0 +1,26 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.gitee.dorive.event.api; + +import com.gitee.dorive.event.entity.EntityEvent; + +public interface EntityEventListener { + + void onEntityEvent(EntityEvent entityEvent); + +} diff --git a/dorive-event/src/main/java/com/gitee/dorive/event/config/DoriveEventConfiguration.java b/dorive-event/src/main/java/com/gitee/dorive/event/config/DoriveEventConfiguration.java index bf15d94721ecca4cc2aacdcd17d6d3ea08a30102..722cbf933f85b4bb84ec8160f7ee88f4bcbd01a2 100644 --- a/dorive-event/src/main/java/com/gitee/dorive/event/config/DoriveEventConfiguration.java +++ b/dorive-event/src/main/java/com/gitee/dorive/event/config/DoriveEventConfiguration.java @@ -17,7 +17,7 @@ package com.gitee.dorive.event.config; -import com.gitee.dorive.event.impl.ExecutorListener; +import com.gitee.dorive.event.impl.ExecutorEventListener; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.Order; @@ -26,9 +26,9 @@ import org.springframework.core.annotation.Order; @Configuration public class DoriveEventConfiguration { - @Bean("executorListenerV3") - public ExecutorListener executorListener() { - return new ExecutorListener(); + @Bean("executorEventListenerV3") + public ExecutorEventListener executorEventListener() { + return new ExecutorEventListener(); } } diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/impl/selector/AllSelector.java b/dorive-event/src/main/java/com/gitee/dorive/event/entity/EntityEvent.java similarity index 73% rename from dorive-core/src/main/java/com/gitee/dorive/core/impl/selector/AllSelector.java rename to dorive-event/src/main/java/com/gitee/dorive/event/entity/EntityEvent.java index bdca51a14265864c533470d51412b58cb764b01e..1c080e1b5dd98f562179732aabc218be9496c0df 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/impl/selector/AllSelector.java +++ b/dorive-event/src/main/java/com/gitee/dorive/event/entity/EntityEvent.java @@ -15,20 +15,19 @@ * limitations under the License. */ -package com.gitee.dorive.core.impl.selector; +package com.gitee.dorive.event.entity; import com.gitee.dorive.core.api.context.Context; -import com.gitee.dorive.core.api.context.Node; +import lombok.AllArgsConstructor; import lombok.Data; -import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; @Data -@EqualsAndHashCode(callSuper = false) -public class AllSelector extends AbstractSelector { - - @Override - public boolean matches(Context context, Node node) { - return true; - } - +@NoArgsConstructor +@AllArgsConstructor +public class EntityEvent { + private ExecutorEvent executorEvent; + private Context context; + private OperationType operationType; + private Object entity; } diff --git a/dorive-coating/src/main/java/com/gitee/dorive/coating/entity/BuildExample.java b/dorive-event/src/main/java/com/gitee/dorive/event/entity/EntityListenerDef.java similarity index 52% rename from dorive-coating/src/main/java/com/gitee/dorive/coating/entity/BuildExample.java rename to dorive-event/src/main/java/com/gitee/dorive/event/entity/EntityListenerDef.java index 1f96fbc1d8a5b189c2faec3d9e1bf0b7d648b4d2..c87d14ca1280e5dafd6eb983ad8fd189cd092f67 100644 --- a/dorive-coating/src/main/java/com/gitee/dorive/coating/entity/BuildExample.java +++ b/dorive-event/src/main/java/com/gitee/dorive/event/entity/EntityListenerDef.java @@ -15,30 +15,31 @@ * limitations under the License. */ -package com.gitee.dorive.coating.entity; +package com.gitee.dorive.event.entity; -import com.gitee.dorive.core.entity.executor.Criterion; -import com.gitee.dorive.core.entity.executor.InnerExample; +import cn.hutool.core.bean.BeanUtil; +import com.gitee.dorive.event.annotation.EntityListener; +import lombok.AllArgsConstructor; import lombok.Data; -import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import org.springframework.core.annotation.AnnotatedElementUtils; -import java.util.List; +import java.lang.reflect.AnnotatedElement; +import java.util.Map; @Data @NoArgsConstructor -@EqualsAndHashCode(callSuper = false) -public class BuildExample extends InnerExample { +@AllArgsConstructor +public class EntityListenerDef { - private boolean abandoned = false; - private boolean countQueried = false; + private Class value; + private OperationType[] subscribeTo; + private boolean afterCommit; + private Class[] rollbackFor; - public BuildExample(List criteria) { - super(criteria); - } - - public boolean isQueryAll() { - return !abandoned && isEmpty(); + public static EntityListenerDef fromElement(AnnotatedElement element) { + Map attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(element, EntityListener.class); + return attributes != null ? BeanUtil.copyProperties(attributes, EntityListenerDef.class) : null; } } diff --git a/dorive-api/src/main/java/com/gitee/dorive/api/constant/OperationType.java b/dorive-event/src/main/java/com/gitee/dorive/event/entity/OperationType.java similarity index 66% rename from dorive-api/src/main/java/com/gitee/dorive/api/constant/OperationType.java rename to dorive-event/src/main/java/com/gitee/dorive/event/entity/OperationType.java index a0a03fbb5729eea215d0a8b64906c44de488149a..a4f859471d647ff80704ec58268f52496376f301 100644 --- a/dorive-api/src/main/java/com/gitee/dorive/api/constant/OperationType.java +++ b/dorive-event/src/main/java/com/gitee/dorive/event/entity/OperationType.java @@ -15,16 +15,11 @@ * limitations under the License. */ -package com.gitee.dorive.api.constant; +package com.gitee.dorive.event.entity; -public interface OperationType { - int NONE = 0x00000000; - int SELECT = 0x00000001; - int INSERT = 0x00000002; - int UPDATE = 0x00000004; - int INSERT_OR_UPDATE = INSERT | UPDATE; - int DELETE = 0x00000008; - int UPDATE_OR_DELETE = UPDATE | DELETE; - int INSERT_OR_UPDATE_OR_DELETE = INSERT | UPDATE | DELETE; - int FORCE_INSERT = 0x00000010 | INSERT; +public enum OperationType { + UNKNOWN, + INSERT, + UPDATE, + DELETE, } diff --git a/dorive-event/src/main/java/com/gitee/dorive/event/impl/EntityEventListenerAdapter.java b/dorive-event/src/main/java/com/gitee/dorive/event/impl/EntityEventListenerAdapter.java new file mode 100644 index 0000000000000000000000000000000000000000..a403fe556213fac5b593e0181b734ce0cd6bbe6d --- /dev/null +++ b/dorive-event/src/main/java/com/gitee/dorive/event/impl/EntityEventListenerAdapter.java @@ -0,0 +1,107 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.gitee.dorive.event.impl; + +import cn.hutool.core.util.ArrayUtil; +import com.gitee.dorive.event.api.EntityEventListener; +import com.gitee.dorive.event.entity.EntityEvent; +import com.gitee.dorive.event.entity.EntityListenerDef; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.core.Ordered; +import org.springframework.transaction.support.TransactionSynchronization; +import org.springframework.transaction.support.TransactionSynchronizationManager; + +@Data +@Slf4j +@NoArgsConstructor +@AllArgsConstructor +public class EntityEventListenerAdapter implements EntityEventListener { + + private Integer order; + private EntityListenerDef entityListenerDef; + private EntityEventListener entityEventListener; + + @Override + public void onEntityEvent(EntityEvent entityEvent) { + boolean isSubscribe = ArrayUtil.contains(entityListenerDef.getSubscribeTo(), entityEvent.getOperationType()); + if (isSubscribe) { + boolean isTxActive = entityListenerDef.isAfterCommit() && TransactionSynchronizationManager.isActualTransactionActive(); + if (!isTxActive) { + handleEntityEvent(entityEvent, true); + } else { + handleEntityEventWhenTxActive(entityEvent); + } + } + } + + private void handleEntityEvent(EntityEvent entityEvent, boolean canRollback) { + try { + entityEventListener.onEntityEvent(entityEvent); + } catch (Throwable throwable) { + if (canRollback && matchRollbackFor(throwable)) { + throw throwable; + } + log.error("Exception occurred in entity event listening!", throwable); + } + } + + private boolean matchRollbackFor(Throwable throwable) { + Class[] rollbackFor = entityListenerDef.getRollbackFor(); + if (rollbackFor != null && rollbackFor.length > 0) { + Class throwableType = throwable.getClass(); + for (Class rollbackType : rollbackFor) { + if (rollbackType.isAssignableFrom(throwableType)) { + return true; + } + } + } + return false; + } + + private void handleEntityEventWhenTxActive(EntityEvent entityEvent) { + try { + TransactionSynchronizationManager.registerSynchronization(new TransactionInvoker(entityEvent)); + } catch (Exception e) { + log.error("Transaction registration failed: " + e.getMessage(), e); + } + } + + /** + * 实现Ordered接口,是为了兼容spring-boot的2.3.2版本与2.7.8版本 + */ + @AllArgsConstructor + private class TransactionInvoker implements TransactionSynchronization, Ordered { + + private final EntityEvent entityEvent; + + @Override + public int getOrder() { + return order; + } + + @Override + public void afterCommit() { + handleEntityEvent(entityEvent, false); + } + + } + +} diff --git a/dorive-event/src/main/java/com/gitee/dorive/event/impl/ExecutorListener.java b/dorive-event/src/main/java/com/gitee/dorive/event/impl/ExecutorEventListener.java similarity index 37% rename from dorive-event/src/main/java/com/gitee/dorive/event/impl/ExecutorListener.java rename to dorive-event/src/main/java/com/gitee/dorive/event/impl/ExecutorEventListener.java index dd0408f119749fdb1cc982c0c584ad3ffbf7b25f..e31dd57f6d7ef8fc708dcf8581fb4cbbea663dff 100644 --- a/dorive-event/src/main/java/com/gitee/dorive/event/impl/ExecutorListener.java +++ b/dorive-event/src/main/java/com/gitee/dorive/event/impl/ExecutorEventListener.java @@ -18,8 +18,16 @@ package com.gitee.dorive.event.impl; import com.gitee.dorive.api.entity.element.EntityEle; -import com.gitee.dorive.event.api.EntityListener; +import com.gitee.dorive.core.api.context.Context; +import com.gitee.dorive.core.entity.operation.Delete; +import com.gitee.dorive.core.entity.operation.Insert; +import com.gitee.dorive.core.entity.operation.Operation; +import com.gitee.dorive.core.entity.operation.Update; +import com.gitee.dorive.event.api.EntityEventListener; +import com.gitee.dorive.event.entity.EntityEvent; +import com.gitee.dorive.event.entity.EntityListenerDef; import com.gitee.dorive.event.entity.ExecutorEvent; +import com.gitee.dorive.event.entity.OperationType; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeansException; import org.springframework.beans.factory.InitializingBean; @@ -27,17 +35,20 @@ import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.ApplicationListener; import org.springframework.core.annotation.AnnotationAwareOrderComparator; +import org.springframework.core.annotation.OrderUtils; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import static org.springframework.core.Ordered.LOWEST_PRECEDENCE; + @Slf4j -public class ExecutorListener implements ApplicationListener, ApplicationContextAware, InitializingBean { +public class ExecutorEventListener implements ApplicationListener, ApplicationContextAware, InitializingBean { private ApplicationContext applicationContext; - private final Map, List> classEventListenersMap = new ConcurrentHashMap<>(); + private final Map, List> classEntityEventListenersMap = new ConcurrentHashMap<>(); @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { @@ -46,15 +57,31 @@ public class ExecutorListener implements ApplicationListener, App @Override public void afterPropertiesSet() { - Map entityListenerMap = applicationContext.getBeansOfType(EntityListener.class); - List entityListeners = new ArrayList<>(entityListenerMap.values()); - entityListeners.sort(new AnnotationAwareOrderComparator()); - for (EntityListener entityListener : entityListeners) { - Class entityClass = entityListener.subscribe(); - if (entityClass != null) { - List existEntityListeners = classEventListenersMap.computeIfAbsent(entityClass, key -> new ArrayList<>(4)); - existEntityListeners.add(entityListener); + Map entityEventListenerMap = applicationContext.getBeansOfType(EntityEventListener.class); + List entityEventListeners = new ArrayList<>(entityEventListenerMap.values()); + AnnotationAwareOrderComparator.sort(entityEventListeners); + + for (EntityEventListener entityEventListener : entityEventListeners) { + Class listenerType = entityEventListener.getClass(); + Integer order = OrderUtils.getOrder(listenerType, LOWEST_PRECEDENCE); + EntityListenerDef entityListenerDef = EntityListenerDef.fromElement(listenerType); + if (entityListenerDef == null) { + continue; + } + Class entityClass = entityListenerDef.getValue(); + if (entityClass == null) { + continue; + } + if (entityEventListener instanceof EntityEventListenerAdapter) { + EntityEventListenerAdapter entityEventListenerAdapter = (EntityEventListenerAdapter) entityEventListener; + entityEventListenerAdapter.setOrder(order); + entityEventListenerAdapter.setEntityListenerDef(entityListenerDef); + + } else { + entityEventListener = new EntityEventListenerAdapter(order, entityListenerDef, entityEventListener); } + List existEntityEventListeners = classEntityEventListenersMap.computeIfAbsent(entityClass, key -> new ArrayList<>(4)); + existEntityEventListeners.add(entityEventListener); } } @@ -63,16 +90,30 @@ public class ExecutorListener implements ApplicationListener, App EventExecutor eventExecutor = (EventExecutor) executorEvent.getSource(); EntityEle entityEle = eventExecutor.getEntityEle(); Class entityClass = entityEle.getGenericType(); - List entityListeners = classEventListenersMap.get(entityClass); - if (entityListeners != null && !entityListeners.isEmpty()) { - for (EntityListener entityListener : entityListeners) { - try { - entityListener.onApplicationEvent(executorEvent); - } catch (Exception e) { - log.error("Exception occurred in event listening!", e); - } + List entityEventListeners = classEntityEventListenersMap.get(entityClass); + if (entityEventListeners != null && !entityEventListeners.isEmpty()) { + EntityEvent entityEvent = newEntityEvent(executorEvent); + for (EntityEventListener entityEventListener : entityEventListeners) { + entityEventListener.onEntityEvent(entityEvent); } } } + private EntityEvent newEntityEvent(ExecutorEvent executorEvent) { + Context context = executorEvent.getContext(); + Operation operation = executorEvent.getOperation(); + OperationType operationType = OperationType.UNKNOWN; + if (operation instanceof Insert) { + operationType = OperationType.INSERT; + + } else if (operation instanceof Update) { + operationType = OperationType.UPDATE; + + } else if (operation instanceof Delete) { + operationType = OperationType.DELETE; + } + Object entity = operation.getEntity(); + return new EntityEvent(executorEvent, context, operationType, entity); + } + } diff --git a/dorive-event/src/main/java/com/gitee/dorive/event/repository/AbstractEventRepository.java b/dorive-event/src/main/java/com/gitee/dorive/event/repository/AbstractEventRepository.java index 34536d6567cffcf06896533cc81e99e4fd440804..c90c7791fde6d56e4290075d6026c98a962d7025 100644 --- a/dorive-event/src/main/java/com/gitee/dorive/event/repository/AbstractEventRepository.java +++ b/dorive-event/src/main/java/com/gitee/dorive/event/repository/AbstractEventRepository.java @@ -19,7 +19,7 @@ package com.gitee.dorive.event.repository; import com.gitee.dorive.api.entity.element.EntityEle; import com.gitee.dorive.core.api.executor.Executor; -import com.gitee.dorive.core.repository.AbstractExampleRepository; +import com.gitee.dorive.core.repository.AbstractGenericRepository; import com.gitee.dorive.core.repository.AbstractProxyRepository; import com.gitee.dorive.core.repository.AbstractRepository; import com.gitee.dorive.core.repository.DefaultRepository; @@ -27,7 +27,7 @@ import com.gitee.dorive.event.annotation.EnableEvent; import com.gitee.dorive.event.impl.EventExecutor; import org.springframework.core.annotation.AnnotationUtils; -public abstract class AbstractEventRepository extends AbstractExampleRepository { +public abstract class AbstractEventRepository extends AbstractGenericRepository { private boolean enableEvent; diff --git a/dorive-injection/pom.xml b/dorive-inject/pom.xml similarity index 92% rename from dorive-injection/pom.xml rename to dorive-inject/pom.xml index a0b771770727491cdedccffa0158cec0771d9840..756bed41cf2ca1f9803040cd45bfe44e47aa6af3 100644 --- a/dorive-injection/pom.xml +++ b/dorive-inject/pom.xml @@ -6,9 +6,9 @@ com.gitee.digital-engine dorive - 3.4.3.1 + 3.4.3.3 - dorive-injection + dorive-inject org.springframework.boot diff --git a/dorive-injection/src/main/java/com/gitee/dorive/injection/annotation/Root.java b/dorive-inject/src/main/java/com/gitee/dorive/inject/annotation/Root.java similarity index 95% rename from dorive-injection/src/main/java/com/gitee/dorive/injection/annotation/Root.java rename to dorive-inject/src/main/java/com/gitee/dorive/inject/annotation/Root.java index f5327262be1fceffe70fa7e732eccc87e20ad5ac..00531fef57d8bc9aefb682bca91192199d40ed24 100644 --- a/dorive-injection/src/main/java/com/gitee/dorive/injection/annotation/Root.java +++ b/dorive-inject/src/main/java/com/gitee/dorive/inject/annotation/Root.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package com.gitee.dorive.injection.annotation; +package com.gitee.dorive.inject.annotation; import java.lang.annotation.*; diff --git a/dorive-injection/src/main/java/com/gitee/dorive/injection/api/TypeDomainResolver.java b/dorive-inject/src/main/java/com/gitee/dorive/inject/api/TypeDomainResolver.java similarity index 91% rename from dorive-injection/src/main/java/com/gitee/dorive/injection/api/TypeDomainResolver.java rename to dorive-inject/src/main/java/com/gitee/dorive/inject/api/TypeDomainResolver.java index d99b70b02ef8e0c11d4b9cbd83db18d30d4da5ea..1ea67118bd84d97c3dc4b380fbf794c5dff5f469 100644 --- a/dorive-injection/src/main/java/com/gitee/dorive/injection/api/TypeDomainResolver.java +++ b/dorive-inject/src/main/java/com/gitee/dorive/inject/api/TypeDomainResolver.java @@ -15,9 +15,9 @@ * limitations under the License. */ -package com.gitee.dorive.injection.api; +package com.gitee.dorive.inject.api; -import com.gitee.dorive.injection.entity.DomainDefinition; +import com.gitee.dorive.inject.entity.DomainDefinition; public interface TypeDomainResolver { diff --git a/dorive-injection/src/main/java/com/gitee/dorive/injection/config/DoriveInjectionConfiguration.java b/dorive-inject/src/main/java/com/gitee/dorive/inject/config/DoriveInjectionConfiguration.java similarity index 88% rename from dorive-injection/src/main/java/com/gitee/dorive/injection/config/DoriveInjectionConfiguration.java rename to dorive-inject/src/main/java/com/gitee/dorive/inject/config/DoriveInjectionConfiguration.java index ae303e916a97f50688b5bb6a7d5148072fbc2e4f..3fd6e0b823b7458d1b5a11db9795764f5d96590d 100644 --- a/dorive-injection/src/main/java/com/gitee/dorive/injection/config/DoriveInjectionConfiguration.java +++ b/dorive-inject/src/main/java/com/gitee/dorive/inject/config/DoriveInjectionConfiguration.java @@ -15,15 +15,15 @@ * limitations under the License. */ -package com.gitee.dorive.injection.config; +package com.gitee.dorive.inject.config; import cn.hutool.core.lang.Assert; -import com.gitee.dorive.injection.impl.DefaultTypeDomainResolver; -import com.gitee.dorive.injection.spring.LimitedAutowiredBeanPostProcessor; -import com.gitee.dorive.injection.spring.LimitedCglibSubclassingInstantiationStrategy; -import com.gitee.dorive.injection.spring.LimitedRootInitializingBean; -import com.gitee.dorive.injection.api.TypeDomainResolver; -import com.gitee.dorive.injection.entity.DomainDefinition; +import com.gitee.dorive.inject.impl.DefaultTypeDomainResolver; +import com.gitee.dorive.inject.spring.LimitedAutowiredBeanPostProcessor; +import com.gitee.dorive.inject.spring.LimitedCglibSubclassingInstantiationStrategy; +import com.gitee.dorive.inject.spring.LimitedRootInitializingBean; +import com.gitee.dorive.inject.api.TypeDomainResolver; +import com.gitee.dorive.inject.entity.DomainDefinition; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; diff --git a/dorive-injection/src/main/java/com/gitee/dorive/injection/entity/DomainDefinition.java b/dorive-inject/src/main/java/com/gitee/dorive/inject/entity/DomainDefinition.java similarity index 95% rename from dorive-injection/src/main/java/com/gitee/dorive/injection/entity/DomainDefinition.java rename to dorive-inject/src/main/java/com/gitee/dorive/inject/entity/DomainDefinition.java index 7411d5869c96b9a23e7c9d99fd15c0dc65413388..afc5e0d17040e2d79e984bd65e0ca9c81fbe6819 100644 --- a/dorive-injection/src/main/java/com/gitee/dorive/injection/entity/DomainDefinition.java +++ b/dorive-inject/src/main/java/com/gitee/dorive/inject/entity/DomainDefinition.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package com.gitee.dorive.injection.entity; +package com.gitee.dorive.inject.entity; import lombok.AllArgsConstructor; import lombok.Data; diff --git a/dorive-injection/src/main/java/com/gitee/dorive/injection/impl/DefaultTypeDomainResolver.java b/dorive-inject/src/main/java/com/gitee/dorive/inject/impl/DefaultTypeDomainResolver.java similarity index 95% rename from dorive-injection/src/main/java/com/gitee/dorive/injection/impl/DefaultTypeDomainResolver.java rename to dorive-inject/src/main/java/com/gitee/dorive/inject/impl/DefaultTypeDomainResolver.java index 45f867d4fc0d0c11e766b8d69c9c0049b3d9fc68..39015df173f3260573d39343c0c64a6ba1e9aaad 100644 --- a/dorive-injection/src/main/java/com/gitee/dorive/injection/impl/DefaultTypeDomainResolver.java +++ b/dorive-inject/src/main/java/com/gitee/dorive/inject/impl/DefaultTypeDomainResolver.java @@ -15,12 +15,12 @@ * limitations under the License. */ -package com.gitee.dorive.injection.impl; +package com.gitee.dorive.inject.impl; import cn.hutool.core.collection.CollUtil; -import com.gitee.dorive.injection.annotation.Root; -import com.gitee.dorive.injection.api.TypeDomainResolver; -import com.gitee.dorive.injection.entity.DomainDefinition; +import com.gitee.dorive.inject.annotation.Root; +import com.gitee.dorive.inject.api.TypeDomainResolver; +import com.gitee.dorive.inject.entity.DomainDefinition; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.BeanCreationException; import org.springframework.core.annotation.AnnotationUtils; diff --git a/dorive-injection/src/main/java/com/gitee/dorive/injection/spring/LimitedAutowiredBeanPostProcessor.java b/dorive-inject/src/main/java/com/gitee/dorive/inject/spring/LimitedAutowiredBeanPostProcessor.java similarity index 97% rename from dorive-injection/src/main/java/com/gitee/dorive/injection/spring/LimitedAutowiredBeanPostProcessor.java rename to dorive-inject/src/main/java/com/gitee/dorive/inject/spring/LimitedAutowiredBeanPostProcessor.java index a9aa8989ecc1fa8905fe92b52f5a7ccfb7bf0146..d28be76eed1cd4ad0bf6614bedca532f2b8d8731 100644 --- a/dorive-injection/src/main/java/com/gitee/dorive/injection/spring/LimitedAutowiredBeanPostProcessor.java +++ b/dorive-inject/src/main/java/com/gitee/dorive/inject/spring/LimitedAutowiredBeanPostProcessor.java @@ -15,9 +15,9 @@ * limitations under the License. */ -package com.gitee.dorive.injection.spring; +package com.gitee.dorive.inject.spring; -import com.gitee.dorive.injection.api.TypeDomainResolver; +import com.gitee.dorive.inject.api.TypeDomainResolver; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.annotation.Autowired; diff --git a/dorive-injection/src/main/java/com/gitee/dorive/injection/spring/LimitedCglibSubclassingInstantiationStrategy.java b/dorive-inject/src/main/java/com/gitee/dorive/inject/spring/LimitedCglibSubclassingInstantiationStrategy.java similarity index 96% rename from dorive-injection/src/main/java/com/gitee/dorive/injection/spring/LimitedCglibSubclassingInstantiationStrategy.java rename to dorive-inject/src/main/java/com/gitee/dorive/inject/spring/LimitedCglibSubclassingInstantiationStrategy.java index 3b24fdf7640815e745078deb2b32b210cbe5978f..50bb20ec9b38f9018a13de72c192ca7b2ac70625 100644 --- a/dorive-injection/src/main/java/com/gitee/dorive/injection/spring/LimitedCglibSubclassingInstantiationStrategy.java +++ b/dorive-inject/src/main/java/com/gitee/dorive/inject/spring/LimitedCglibSubclassingInstantiationStrategy.java @@ -15,9 +15,9 @@ * limitations under the License. */ -package com.gitee.dorive.injection.spring; +package com.gitee.dorive.inject.spring; -import com.gitee.dorive.injection.api.TypeDomainResolver; +import com.gitee.dorive.inject.api.TypeDomainResolver; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.support.CglibSubclassingInstantiationStrategy; import org.springframework.beans.factory.support.RootBeanDefinition; diff --git a/dorive-injection/src/main/java/com/gitee/dorive/injection/spring/LimitedRootInitializingBean.java b/dorive-inject/src/main/java/com/gitee/dorive/inject/spring/LimitedRootInitializingBean.java similarity index 90% rename from dorive-injection/src/main/java/com/gitee/dorive/injection/spring/LimitedRootInitializingBean.java rename to dorive-inject/src/main/java/com/gitee/dorive/inject/spring/LimitedRootInitializingBean.java index 857f5124fdc72bb529c3e279683bbc40fe4b4734..be189da01cd1275f04d9fc707a47c0eacafa5b05 100644 --- a/dorive-injection/src/main/java/com/gitee/dorive/injection/spring/LimitedRootInitializingBean.java +++ b/dorive-inject/src/main/java/com/gitee/dorive/inject/spring/LimitedRootInitializingBean.java @@ -15,11 +15,11 @@ * limitations under the License. */ -package com.gitee.dorive.injection.spring; +package com.gitee.dorive.inject.spring; -import com.gitee.dorive.injection.annotation.Root; -import com.gitee.dorive.injection.api.TypeDomainResolver; -import com.gitee.dorive.injection.util.AopUtils; +import com.gitee.dorive.inject.annotation.Root; +import com.gitee.dorive.inject.api.TypeDomainResolver; +import com.gitee.dorive.inject.util.AopUtils; import org.springframework.beans.BeansException; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.ApplicationContext; diff --git a/dorive-injection/src/main/java/com/gitee/dorive/injection/util/AopUtils.java b/dorive-inject/src/main/java/com/gitee/dorive/inject/util/AopUtils.java similarity index 97% rename from dorive-injection/src/main/java/com/gitee/dorive/injection/util/AopUtils.java rename to dorive-inject/src/main/java/com/gitee/dorive/inject/util/AopUtils.java index 0e6818e1aab304f65a84f9c23ef9a79fec81131e..ba2e194beb721d9144fbadeab980e7804873677b 100644 --- a/dorive-injection/src/main/java/com/gitee/dorive/injection/util/AopUtils.java +++ b/dorive-inject/src/main/java/com/gitee/dorive/inject/util/AopUtils.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package com.gitee.dorive.injection.util; +package com.gitee.dorive.inject.util; import java.lang.annotation.Annotation; diff --git a/dorive-injection/src/main/resources/META-INF/spring-configuration-metadata.json b/dorive-inject/src/main/resources/META-INF/spring-configuration-metadata.json similarity index 84% rename from dorive-injection/src/main/resources/META-INF/spring-configuration-metadata.json rename to dorive-inject/src/main/resources/META-INF/spring-configuration-metadata.json index 271567594c0ea0493d606cb9ab7a37e1785d9692..b4633a7447f4b5e68a2f573064e5e67c0274b380 100644 --- a/dorive-injection/src/main/resources/META-INF/spring-configuration-metadata.json +++ b/dorive-inject/src/main/resources/META-INF/spring-configuration-metadata.json @@ -12,7 +12,7 @@ }, { "name": "dorive.domains", - "type": "com.gitee.dorive.injection.entity.DomainDefinition", + "type": "com.gitee.dorive.inject.entity.DomainDefinition", "description": "Definition of domain." } ] diff --git a/dorive-injection/src/main/resources/META-INF/spring.factories b/dorive-inject/src/main/resources/META-INF/spring.factories similarity index 50% rename from dorive-injection/src/main/resources/META-INF/spring.factories rename to dorive-inject/src/main/resources/META-INF/spring.factories index 0b2fbfbef5ea272e0a1c92e0db4b278df61bd83c..120be675f381fd77c0b40bab5883a90932d110ca 100644 --- a/dorive-injection/src/main/resources/META-INF/spring.factories +++ b/dorive-inject/src/main/resources/META-INF/spring.factories @@ -1,2 +1,2 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ - com.gitee.dorive.injection.config.DoriveInjectionConfiguration \ No newline at end of file + com.gitee.dorive.inject.config.DoriveInjectionConfiguration \ No newline at end of file diff --git a/dorive-inject/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/dorive-inject/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 0000000000000000000000000000000000000000..72e2562d2f782e68b08c239fa0c9bd8b576626b3 --- /dev/null +++ b/dorive-inject/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +com.gitee.dorive.inject.config.DoriveInjectionConfiguration \ No newline at end of file diff --git a/dorive-injection/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/dorive-injection/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports deleted file mode 100644 index 16035200ac4f785856fe10ad8c3a6938abd04d74..0000000000000000000000000000000000000000 --- a/dorive-injection/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ /dev/null @@ -1 +0,0 @@ -com.gitee.dorive.injection.config.DoriveInjectionConfiguration \ No newline at end of file diff --git a/dorive-mybatis-plus/pom.xml b/dorive-mybatis-plus/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..03be052251ad48afa462bbbe5964c1e6cf962c7d --- /dev/null +++ b/dorive-mybatis-plus/pom.xml @@ -0,0 +1,28 @@ + + + 4.0.0 + + com.gitee.digital-engine + dorive + 3.4.3.3 + + dorive-mybatis-plus + + + com.gitee.digital-engine + dorive-env + ${project.version} + + + com.gitee.digital-engine + dorive-sql + ${project.version} + + + com.baomidou + mybatis-plus-boot-starter + + + \ No newline at end of file diff --git a/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/api/CriterionAppender.java b/dorive-mybatis-plus/src/main/java/com/gitee/dorive/mybatis/plus/api/CriterionAppender.java similarity index 95% rename from dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/api/CriterionAppender.java rename to dorive-mybatis-plus/src/main/java/com/gitee/dorive/mybatis/plus/api/CriterionAppender.java index e26913367bad451d2d33c7de946b99d58af55f47..13e90e54d174c65a0a9c19b9f7910aba334560cc 100644 --- a/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/api/CriterionAppender.java +++ b/dorive-mybatis-plus/src/main/java/com/gitee/dorive/mybatis/plus/api/CriterionAppender.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package com.gitee.dorive.spring.boot.starter.api; +package com.gitee.dorive.mybatis.plus.api; import com.baomidou.mybatisplus.core.conditions.AbstractWrapper; diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/entity/operation/NullableUpdate.java b/dorive-mybatis-plus/src/main/java/com/gitee/dorive/mybatis/plus/config/DoriveMybatisPlusConfiguration.java similarity index 62% rename from dorive-core/src/main/java/com/gitee/dorive/core/entity/operation/NullableUpdate.java rename to dorive-mybatis-plus/src/main/java/com/gitee/dorive/mybatis/plus/config/DoriveMybatisPlusConfiguration.java index 3d1061edc3f702aaafa6622ba8aee9c94cb73b35..24e2649a4bd1dce4083ad401d0e040ad0f09ea31 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/entity/operation/NullableUpdate.java +++ b/dorive-mybatis-plus/src/main/java/com/gitee/dorive/mybatis/plus/config/DoriveMybatisPlusConfiguration.java @@ -15,26 +15,21 @@ * limitations under the License. */ -package com.gitee.dorive.core.entity.operation; +package com.gitee.dorive.mybatis.plus.config; -import com.gitee.dorive.api.constant.OperationType; -import lombok.Getter; -import lombok.Setter; +import com.gitee.dorive.mybatis.plus.impl.DefaultImplFactory; +import com.gitee.dorive.api.api.ImplFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.annotation.Order; -import java.util.Set; +@Order(-100) +@Configuration +public class DoriveMybatisPlusConfiguration { -@Getter -@Setter -public class NullableUpdate extends Update { - - private Set nullableSet; - - public NullableUpdate(int type, Object entity) { - super(type, entity); - } - - public NullableUpdate(Object entity) { - super(OperationType.UPDATE, entity); + @Bean + public static ImplFactory implFactory() { + return new DefaultImplFactory(); } } diff --git a/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/config/MybatisPlusConfiguration.java b/dorive-mybatis-plus/src/main/java/com/gitee/dorive/mybatis/plus/config/MybatisPlusConfiguration.java similarity index 97% rename from dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/config/MybatisPlusConfiguration.java rename to dorive-mybatis-plus/src/main/java/com/gitee/dorive/mybatis/plus/config/MybatisPlusConfiguration.java index 9d33ecf38fb34b1d79ab55968b06c0f3501dfa49..43f64b04fc81d843610270c2ad16a042090668b6 100644 --- a/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/config/MybatisPlusConfiguration.java +++ b/dorive-mybatis-plus/src/main/java/com/gitee/dorive/mybatis/plus/config/MybatisPlusConfiguration.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package com.gitee.dorive.spring.boot.starter.config; +package com.gitee.dorive.mybatis.plus.config; import com.baomidou.mybatisplus.annotation.DbType; import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; diff --git a/dorive-mybatis-plus/src/main/java/com/gitee/dorive/mybatis/plus/entity/LambdaExample.java b/dorive-mybatis-plus/src/main/java/com/gitee/dorive/mybatis/plus/entity/LambdaExample.java new file mode 100644 index 0000000000000000000000000000000000000000..5d365051fcaada1aa6fa7c19e20c378ac9a1961a --- /dev/null +++ b/dorive-mybatis-plus/src/main/java/com/gitee/dorive/mybatis/plus/entity/LambdaExample.java @@ -0,0 +1,151 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.gitee.dorive.mybatis.plus.entity; + +import com.baomidou.mybatisplus.core.toolkit.support.SFunction; +import com.gitee.dorive.api.constant.Operator; +import com.gitee.dorive.core.entity.executor.Criterion; +import com.gitee.dorive.core.entity.executor.Example; +import com.gitee.dorive.mybatis.plus.util.LambdaUtils; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.function.Consumer; + +@Data +@NoArgsConstructor +@EqualsAndHashCode(callSuper = false) +public class LambdaExample extends Example { + + private List toProperties(SFunction[] functions) { + if (functions != null && functions.length > 0) { + List properties = new ArrayList<>(functions.length); + for (SFunction function : functions) { + properties.add(LambdaUtils.toProperty(function)); + } + return properties; + } + return Collections.emptyList(); + } + + @SafeVarargs + public final LambdaExample select(SFunction... functions) { + List properties = toProperties(functions); + if (!properties.isEmpty()) { + super.select(properties); + } + return this; + } + + public LambdaExample eq(SFunction function, Object value) { + super.eq(LambdaUtils.toProperty(function), value); + return this; + } + + public LambdaExample ne(SFunction function, Object value) { + super.ne(LambdaUtils.toProperty(function), value); + return this; + } + + public LambdaExample gt(SFunction function, Object value) { + super.gt(LambdaUtils.toProperty(function), value); + return this; + } + + public LambdaExample ge(SFunction function, Object value) { + super.ge(LambdaUtils.toProperty(function), value); + return this; + } + + public LambdaExample lt(SFunction function, Object value) { + super.lt(LambdaUtils.toProperty(function), value); + return this; + } + + public LambdaExample le(SFunction function, Object value) { + super.le(LambdaUtils.toProperty(function), value); + return this; + } + + public LambdaExample in(SFunction function, Object value) { + super.in(LambdaUtils.toProperty(function), value); + return this; + } + + public LambdaExample notIn(SFunction function, Object value) { + super.notIn(LambdaUtils.toProperty(function), value); + return this; + } + + public LambdaExample like(SFunction function, Object value) { + super.like(LambdaUtils.toProperty(function), value); + return this; + } + + public LambdaExample notLike(SFunction function, Object value) { + super.notLike(LambdaUtils.toProperty(function), value); + return this; + } + + public LambdaExample isNull(SFunction function) { + super.isNull(LambdaUtils.toProperty(function)); + return this; + } + + public LambdaExample isNotNull(SFunction function) { + super.isNotNull(LambdaUtils.toProperty(function)); + return this; + } + + public LambdaExample lambdaAnd(Consumer> consumer) { + LambdaExample example = new LambdaExample<>(); + consumer.accept(example); + getCriteria().add(new Criterion("@Lambda", Operator.AND, example)); + return this; + } + + public LambdaExample lambdaOr(Consumer> consumer) { + LambdaExample example = new LambdaExample<>(); + consumer.accept(example); + getCriteria().add(new Criterion("@Lambda", Operator.OR, example)); + return this; + } + + @SafeVarargs + public final LambdaExample orderByAsc(SFunction... functions) { + List properties = toProperties(functions); + if (!properties.isEmpty()) { + super.orderByAsc(properties.toArray(new String[0])); + } + return this; + } + + @SafeVarargs + public final LambdaExample orderByDesc(SFunction... functions) { + List properties = toProperties(functions); + if (!properties.isEmpty()) { + super.orderByDesc(properties.toArray(new String[0])); + } + return this; + } + +} diff --git a/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/impl/AppenderContext.java b/dorive-mybatis-plus/src/main/java/com/gitee/dorive/mybatis/plus/impl/AppenderContext.java similarity index 58% rename from dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/impl/AppenderContext.java rename to dorive-mybatis-plus/src/main/java/com/gitee/dorive/mybatis/plus/impl/AppenderContext.java index ec31c3f3da1805d33263ad4d77b688776951ad13..93e8566268aba3dd778a70d6f9535e5116f6ffbc 100644 --- a/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/impl/AppenderContext.java +++ b/dorive-mybatis-plus/src/main/java/com/gitee/dorive/mybatis/plus/impl/AppenderContext.java @@ -15,20 +15,18 @@ * limitations under the License. */ -package com.gitee.dorive.spring.boot.starter.impl; +package com.gitee.dorive.mybatis.plus.impl; +import com.baomidou.mybatisplus.core.conditions.AbstractWrapper; import com.baomidou.mybatisplus.core.conditions.interfaces.Compare; -import com.baomidou.mybatisplus.core.toolkit.StringUtils; import com.gitee.dorive.api.constant.Operator; -import com.gitee.dorive.core.entity.executor.MultiInBuilder; -import com.gitee.dorive.spring.boot.starter.api.CriterionAppender; -import com.gitee.dorive.spring.boot.starter.util.SqlUtils; +import com.gitee.dorive.core.entity.executor.Criterion; +import com.gitee.dorive.core.entity.executor.Example; +import com.gitee.dorive.mybatis.plus.api.CriterionAppender; import java.util.Collection; -import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; -import java.util.stream.Collectors; public class AppenderContext { @@ -55,41 +53,35 @@ public class AppenderContext { OPERATOR_CRITERION_APPENDER_MAP.put(Operator.LE, Compare::le); OPERATOR_CRITERION_APPENDER_MAP.put(Operator.IN, (abstractWrapper, property, value) -> abstractWrapper.in(property, (Collection) value)); OPERATOR_CRITERION_APPENDER_MAP.put(Operator.NOT_IN, (abstractWrapper, property, value) -> abstractWrapper.notIn(property, (Collection) value)); - OPERATOR_CRITERION_APPENDER_MAP.put(Operator.LIKE, (abstractWrapper, property, value) -> abstractWrapper.like(property, SqlUtils.toLike(value))); - OPERATOR_CRITERION_APPENDER_MAP.put(Operator.NOT_LIKE, (abstractWrapper, property, value) -> abstractWrapper.notLike(property, SqlUtils.toLike(value))); + OPERATOR_CRITERION_APPENDER_MAP.put(Operator.LIKE, Compare::like); + OPERATOR_CRITERION_APPENDER_MAP.put(Operator.NOT_LIKE, Compare::notLike); OPERATOR_CRITERION_APPENDER_MAP.put(Operator.IS_NULL, (abstractWrapper, property, value) -> abstractWrapper.isNull(property)); OPERATOR_CRITERION_APPENDER_MAP.put(Operator.IS_NOT_NULL, (abstractWrapper, property, value) -> abstractWrapper.isNotNull(property)); - OPERATOR_CRITERION_APPENDER_MAP.put(Operator.NULL_SWITCH, (abstractWrapper, property, value) -> { - if (value instanceof Boolean) { - if ((Boolean) value) { - abstractWrapper.isNull(property); - } else { - abstractWrapper.isNotNull(property); - } + OPERATOR_CRITERION_APPENDER_MAP.put(Operator.MULTI_IN, (abstractWrapper, property, value) -> { + String prefix = abstractWrapper.isEmptyOfWhere() ? " WHERE " : " AND "; + abstractWrapper.last(prefix + "(" + property + ") IN (" + value + ")"); + }); + OPERATOR_CRITERION_APPENDER_MAP.put(Operator.MULTI_NOT_IN, (abstractWrapper, property, value) -> { + String prefix = abstractWrapper.isEmptyOfWhere() ? " WHERE " : " AND "; + abstractWrapper.last(prefix + "(" + property + ") NOT IN (" + value + ")"); + }); + OPERATOR_CRITERION_APPENDER_MAP.put(Operator.AND, (abstractWrapper, property, value) -> { + if (value instanceof Example) { + abstractWrapper.and(q -> appendCriterion(q, (Example) value)); } }); - OPERATOR_CRITERION_APPENDER_MAP.put(Operator.MULTI_IN, (abstractWrapper, property, value) -> { - if (value instanceof MultiInBuilder) { - MultiInBuilder builder = (MultiInBuilder) value; - StringBuilder valuesStr = new StringBuilder(); - for (int page = 1; page <= builder.page(); page++) { - List values = builder.get(page); - valuesStr.append(buildValuesStr(values)); - } - if (valuesStr.length() > 0) { - valuesStr.deleteCharAt(valuesStr.length() - 1); - } - if (abstractWrapper.isEmptyOfWhere()) { - abstractWrapper.last(" WHERE (" + property + ") IN (" + valuesStr + ")"); - } else { - abstractWrapper.last(" AND (" + property + ") IN (" + valuesStr + ")"); - } + OPERATOR_CRITERION_APPENDER_MAP.put(Operator.OR, (abstractWrapper, property, value) -> { + if (value instanceof Example) { + abstractWrapper.or(q -> appendCriterion(q, (Example) value)); } }); } - public static String buildValuesStr(List values) { - return values.stream().map(StringUtils::sqlParam).collect(Collectors.joining(",", "(", "),")); + public static void appendCriterion(AbstractWrapper abstractWrapper, Example example) { + for (Criterion criterion : example.getCriteria()) { + CriterionAppender criterionAppender = OPERATOR_CRITERION_APPENDER_MAP.get(criterion.getOperator()); + criterionAppender.appendCriterion(abstractWrapper, criterion.getProperty(), criterion.getValue()); + } } } diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/impl/selector/EmptySelector.java b/dorive-mybatis-plus/src/main/java/com/gitee/dorive/mybatis/plus/impl/DefaultImplFactory.java similarity index 60% rename from dorive-core/src/main/java/com/gitee/dorive/core/impl/selector/EmptySelector.java rename to dorive-mybatis-plus/src/main/java/com/gitee/dorive/mybatis/plus/impl/DefaultImplFactory.java index 5eaa51219b289b68b3f37cbc246e84479e24d641..a71e7be036429e0ae48601539ecbe7c54f31a088 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/impl/selector/EmptySelector.java +++ b/dorive-mybatis-plus/src/main/java/com/gitee/dorive/mybatis/plus/impl/DefaultImplFactory.java @@ -15,20 +15,24 @@ * limitations under the License. */ -package com.gitee.dorive.core.impl.selector; +package com.gitee.dorive.mybatis.plus.impl; -import com.gitee.dorive.core.api.context.Context; -import com.gitee.dorive.core.api.context.Node; -import lombok.Data; -import lombok.EqualsAndHashCode; +import com.gitee.dorive.api.api.ImplFactory; +import com.gitee.dorive.core.api.format.SqlFormat; +import com.gitee.dorive.sql.api.SqlRunner; -@Data -@EqualsAndHashCode(callSuper = false) -public class EmptySelector extends AbstractSelector { +public class DefaultImplFactory implements ImplFactory { @Override - public boolean matches(Context context, Node node) { - return false; + @SuppressWarnings("unchecked") + public T getInstance(Class clazz, Object... args) { + if (clazz == SqlFormat.class) { + return (T) new DefaultSqlHelper(); + + } else if (clazz == SqlRunner.class) { + return (T) new DefaultSqlHelper(); + } + return null; } } diff --git a/dorive-mybatis-plus/src/main/java/com/gitee/dorive/mybatis/plus/impl/DefaultSqlHelper.java b/dorive-mybatis-plus/src/main/java/com/gitee/dorive/mybatis/plus/impl/DefaultSqlHelper.java new file mode 100644 index 0000000000000000000000000000000000000000..0a2b22111ddbf470fb124da7a7f68014223cdb14 --- /dev/null +++ b/dorive-mybatis-plus/src/main/java/com/gitee/dorive/mybatis/plus/impl/DefaultSqlHelper.java @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.gitee.dorive.mybatis.plus.impl; + +import cn.hutool.db.sql.Condition; +import cn.hutool.db.sql.SqlUtil; +import com.baomidou.mybatisplus.core.toolkit.StringUtils; +import com.gitee.dorive.core.api.format.SqlFormat; +import com.gitee.dorive.sql.api.SqlRunner; + +import java.util.List; +import java.util.Map; + +public class DefaultSqlHelper implements SqlFormat, SqlRunner { + + @Override + public Object concatLike(Object value) { + if (value instanceof String) { + String valueStr = (String) value; + if (!valueStr.startsWith("%") && !valueStr.endsWith("%")) { + return SqlUtil.buildLikeValue(valueStr, Condition.LikeType.Contains, false); + } + } + return value; + } + + @Override + public String sqlParam(Object obj) { + return StringUtils.sqlParam(obj); + } + + @Override + public long selectCount(String sql, Object... args) { + return com.baomidou.mybatisplus.extension.toolkit.SqlRunner.db().selectCount(sql, args); + } + + @Override + public List> selectList(String sql, Object... args) { + return com.baomidou.mybatisplus.extension.toolkit.SqlRunner.db().selectList(sql, args); + } + +} diff --git a/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/impl/executor/MybatisPlusExecutor.java b/dorive-mybatis-plus/src/main/java/com/gitee/dorive/mybatis/plus/impl/MybatisPlusExecutor.java similarity index 44% rename from dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/impl/executor/MybatisPlusExecutor.java rename to dorive-mybatis-plus/src/main/java/com/gitee/dorive/mybatis/plus/impl/MybatisPlusExecutor.java index c438df9e0afa42c47d84ac4fdd7cbec438e2a434..d917410e521be830fc3d4d6a79b9591ede49a7f3 100644 --- a/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/impl/executor/MybatisPlusExecutor.java +++ b/dorive-mybatis-plus/src/main/java/com/gitee/dorive/mybatis/plus/impl/MybatisPlusExecutor.java @@ -15,28 +15,28 @@ * limitations under the License. */ -package com.gitee.dorive.spring.boot.starter.impl.executor; +package com.gitee.dorive.mybatis.plus.impl; import cn.hutool.core.bean.BeanUtil; -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.lang.Assert; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.baomidou.mybatisplus.core.metadata.TableFieldInfo; -import com.baomidou.mybatisplus.core.metadata.TableInfoHelper; import com.baomidou.mybatisplus.core.toolkit.StringPool; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.gitee.dorive.api.constant.Operator; import com.gitee.dorive.api.constant.Order; import com.gitee.dorive.api.entity.def.EntityDef; import com.gitee.dorive.api.entity.element.EntityEle; import com.gitee.dorive.core.api.context.Context; -import com.gitee.dorive.core.entity.executor.*; -import com.gitee.dorive.core.entity.operation.*; +import com.gitee.dorive.core.entity.common.EntityStoreInfo; +import com.gitee.dorive.core.entity.executor.Example; +import com.gitee.dorive.core.entity.executor.OrderBy; +import com.gitee.dorive.core.entity.executor.Result; +import com.gitee.dorive.core.entity.operation.Delete; +import com.gitee.dorive.core.entity.operation.Insert; +import com.gitee.dorive.core.entity.operation.Operation; +import com.gitee.dorive.core.entity.operation.Query; +import com.gitee.dorive.core.entity.operation.Update; import com.gitee.dorive.core.impl.executor.AbstractExecutor; -import com.gitee.dorive.spring.boot.starter.api.CriterionAppender; -import com.gitee.dorive.spring.boot.starter.util.CriterionUtils; import lombok.Getter; import lombok.Setter; import lombok.ToString; @@ -48,8 +48,6 @@ import java.util.List; import java.util.Map; import java.util.Set; -import static com.gitee.dorive.spring.boot.starter.impl.AppenderContext.OPERATOR_CRITERION_APPENDER_MAP; - @Getter @Setter @ToString @@ -57,54 +55,45 @@ public class MybatisPlusExecutor extends AbstractExecutor { private EntityDef entityDef; private EntityEle entityEle; + private EntityStoreInfo entityStoreInfo; private BaseMapper baseMapper; private Class pojoClass; - public MybatisPlusExecutor(EntityDef entityDef, - EntityEle entityEle, - BaseMapper baseMapper, - Class pojoClass) { + @SuppressWarnings("unchecked") + public MybatisPlusExecutor(EntityDef entityDef, EntityEle entityEle, EntityStoreInfo entityStoreInfo) { this.entityDef = entityDef; this.entityEle = entityEle; - this.baseMapper = baseMapper; - this.pojoClass = pojoClass; + this.entityStoreInfo = entityStoreInfo; + this.baseMapper = (BaseMapper) entityStoreInfo.getMapper(); + this.pojoClass = (Class) entityStoreInfo.getPojoClass(); } @Override public Result executeQuery(Context context, Query query) { - if (query.getPrimaryKey() != null) { + Object primaryKey = query.getPrimaryKey(); + if (primaryKey != null) { QueryWrapper queryWrapper = new QueryWrapper<>(); - queryWrapper.eq("id", query.getPrimaryKey()); + queryWrapper.eq(entityStoreInfo.getIdColumn(), primaryKey); List> resultMaps = baseMapper.selectMaps(queryWrapper); - return new MultiResult(resultMaps); - - } else if (query.getExample() != null) { - Example example = query.getExample(); - if (query.startPage()) { - com.gitee.dorive.core.entity.executor.Page page = example.getPage(); - - Page> queryPage = new Page<>(page.getCurrent(), page.getSize()); - QueryWrapper queryWrapper = buildQueryWrapper(example); - queryPage = baseMapper.selectMapsPage(queryPage, queryWrapper); + return new Result<>(null, resultMaps); + } + Example example = query.getExample(); + if (example != null) { + QueryWrapper queryWrapper = buildQueryWrapper(example); + com.gitee.dorive.core.entity.executor.Page page = example.getPage(); + if (page != null) { + Page> queryPage = baseMapper.selectMapsPage(new Page<>(page.getCurrent(), page.getSize()), queryWrapper); page.setTotal(queryPage.getTotal()); - return new MultiResult(page, queryPage.getRecords()); + return new Result<>(page, queryPage.getRecords()); } else { - if (example instanceof UnionExample) { - UnionExample unionExample = (UnionExample) example; - QueryWrapper queryWrapper = buildQueryWrapper(unionExample); - List> resultMaps = baseMapper.selectMaps(queryWrapper); - return new MultiResult(resultMaps); - - } else { - QueryWrapper queryWrapper = buildQueryWrapper(example); - List> resultMaps = baseMapper.selectMaps(queryWrapper); - return new MultiResult(resultMaps); - } + List> resultMaps = baseMapper.selectMaps(queryWrapper); + return new Result<>(null, resultMaps); } } - return new MultiResult(Collections.emptyList()); + + return new Result<>(null, Collections.emptyList()); } @Override @@ -125,20 +114,16 @@ public class MybatisPlusExecutor extends AbstractExecutor { queryWrapper.select(selectProps); } - List extraProps = example.getExtraProps(); - if (extraProps != null && !extraProps.isEmpty()) { + String selectSuffix = example.getSelectSuffix(); + if (StringUtils.isNotBlank(selectSuffix)) { String sqlSelect = queryWrapper.getSqlSelect(); if (StringUtils.isBlank(sqlSelect)) { sqlSelect = queryWrapper.select(pojoClass, i -> true).getSqlSelect(); } - sqlSelect = sqlSelect + StringPool.COMMA + queryWrapper.select(extraProps).getSqlSelect(); - queryWrapper.select(sqlSelect); + queryWrapper.select(sqlSelect + StringPool.COMMA + selectSuffix); } - for (Criterion criterion : example.getCriteria()) { - CriterionAppender criterionAppender = OPERATOR_CRITERION_APPENDER_MAP.get(criterion.getOperator()); - criterionAppender.appendCriterion(queryWrapper, criterion.getProperty(), criterion.getValue()); - } + AppenderContext.appendCriterion(queryWrapper, example); OrderBy orderBy = example.getOrderBy(); if (orderBy != null) { @@ -154,48 +139,6 @@ public class MybatisPlusExecutor extends AbstractExecutor { return queryWrapper; } - private QueryWrapper buildQueryWrapper(UnionExample unionExample) { - List examples = unionExample.getExamples(); - Assert.notEmpty(examples, "The examples cannot be empty!"); - - Example example = examples.get(0); - QueryWrapper queryWrapper = buildQueryWrapper(example); - - StringBuilder lastSql = new StringBuilder(); - if (example.getPage() != null) { - lastSql.append(example.getPage()).append(" "); - } - - for (int index = 1; index < examples.size(); index++) { - Example nextExample = examples.get(index); - QueryWrapper nextQueryWrapper = buildQueryWrapper(nextExample); - - String sqlSelect = nextQueryWrapper.getSqlSelect(); - String tableName = TableInfoHelper.getTableInfo(pojoClass).getTableName(); - String criteria = CollUtil.join(nextExample.getCriteria(), " AND ", CriterionUtils::toString); - - String sql = ""; - if (nextExample.getOrderBy() == null && nextExample.getPage() == null) { - sql = String.format("UNION ALL (SELECT %s FROM %s WHERE %s) ", sqlSelect, tableName, criteria); - - } else if (nextExample.getOrderBy() != null && nextExample.getPage() != null) { - sql = String.format("UNION ALL (SELECT %s FROM %s WHERE %s %s %s) ", sqlSelect, tableName, criteria, nextExample.getOrderBy(), nextExample.getPage()); - - } else if (nextExample.getOrderBy() != null) { - sql = String.format("UNION ALL (SELECT %s FROM %s WHERE %s %s) ", sqlSelect, tableName, criteria, nextExample.getOrderBy()); - - } else if (nextExample.getPage() != null) { - sql = String.format("UNION ALL (SELECT %s FROM %s WHERE %s %s) ", sqlSelect, tableName, criteria, nextExample.getPage()); - } - lastSql.append(sql); - } - - if (lastSql.length() > 0) { - queryWrapper.last(lastSql.toString()); - } - return queryWrapper; - } - @Override public int execute(Context context, Operation operation) { Object persistent = operation.getEntity(); @@ -208,13 +151,10 @@ public class MybatisPlusExecutor extends AbstractExecutor { Object primaryKey = update.getPrimaryKey(); Example example = update.getExample(); - if (update instanceof NullableUpdate) { - NullableUpdate nullableUpdate = (NullableUpdate) update; - Set nullableSet = nullableUpdate.getNullableSet(); - if (nullableSet != null && !nullableSet.isEmpty()) { - UpdateWrapper updateWrapper = buildUpdateWrapper(persistent, nullableSet, primaryKey, example); - return baseMapper.update(null, updateWrapper); - } + Set nullableProps = update.getNullableProps(); + if (nullableProps != null && !nullableProps.isEmpty()) { + UpdateWrapper updateWrapper = buildUpdateWrapper(persistent, nullableProps, primaryKey, example); + return baseMapper.update(null, updateWrapper); } if (primaryKey != null) { @@ -241,32 +181,26 @@ public class MybatisPlusExecutor extends AbstractExecutor { private UpdateWrapper buildUpdateWrapper(Example example) { UpdateWrapper updateWrapper = new UpdateWrapper<>(); - for (Criterion criterion : example.getCriteria()) { - CriterionAppender criterionAppender = OPERATOR_CRITERION_APPENDER_MAP.get(criterion.getOperator()); - criterionAppender.appendCriterion(updateWrapper, criterion.getProperty(), criterion.getValue()); - } + AppenderContext.appendCriterion(updateWrapper, example); return updateWrapper; } - private UpdateWrapper buildUpdateWrapper(Object persistent, Set nullableSet, Object primaryKey, Example example) { + private UpdateWrapper buildUpdateWrapper(Object persistent, Set nullableProps, Object primaryKey, Example example) { UpdateWrapper updateWrapper = new UpdateWrapper<>(); - List fieldList = TableInfoHelper.getTableInfo(pojoClass).getFieldList(); - for (TableFieldInfo tableFieldInfo : fieldList) { - String property = tableFieldInfo.getProperty(); - Object value = BeanUtil.getFieldValue(persistent, property); - if (value != null || nullableSet.contains(property)) { - updateWrapper.set(true, tableFieldInfo.getColumn(), value); + + Map propAliasMappingWithoutPk = entityStoreInfo.getPropAliasMappingWithoutPk(); + propAliasMappingWithoutPk.forEach((prop, alias) -> { + Object value = BeanUtil.getFieldValue(persistent, prop); + if (value != null || nullableProps.contains(alias)) { + updateWrapper.set(true, alias, value); } - } + }); + if (primaryKey != null) { - CriterionAppender criterionAppender = OPERATOR_CRITERION_APPENDER_MAP.get(Operator.EQ); - criterionAppender.appendCriterion(updateWrapper, "id", primaryKey); + updateWrapper.eq(entityStoreInfo.getIdColumn(), primaryKey); } if (example != null) { - for (Criterion criterion : example.getCriteria()) { - CriterionAppender criterionAppender = OPERATOR_CRITERION_APPENDER_MAP.get(criterion.getOperator()); - criterionAppender.appendCriterion(updateWrapper, criterion.getProperty(), criterion.getValue()); - } + AppenderContext.appendCriterion(updateWrapper, example); } return updateWrapper; } diff --git a/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/repository/MybatisPlusRepository.java b/dorive-mybatis-plus/src/main/java/com/gitee/dorive/mybatis/plus/repository/MybatisPlusRepository.java similarity index 41% rename from dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/repository/MybatisPlusRepository.java rename to dorive-mybatis-plus/src/main/java/com/gitee/dorive/mybatis/plus/repository/MybatisPlusRepository.java index 400f3ad53f9d73ec27d2a7c1f9cf3cf6d6c840a2..de7641a7e48520f68e3aef93b2ec7b2669f50b49 100644 --- a/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/repository/MybatisPlusRepository.java +++ b/dorive-mybatis-plus/src/main/java/com/gitee/dorive/mybatis/plus/repository/MybatisPlusRepository.java @@ -15,61 +15,67 @@ * limitations under the License. */ -package com.gitee.dorive.spring.boot.starter.repository; +package com.gitee.dorive.mybatis.plus.repository; import cn.hutool.core.lang.Assert; -import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.metadata.TableFieldInfo; import com.baomidou.mybatisplus.core.metadata.TableInfo; import com.baomidou.mybatisplus.core.metadata.TableInfoHelper; -import com.gitee.dorive.api.constant.Keys; +import com.gitee.dorive.api.api.ImplFactory; import com.gitee.dorive.api.entity.def.EntityDef; import com.gitee.dorive.api.entity.element.EntityEle; -import com.gitee.dorive.coating.api.ExampleBuilder; -import com.gitee.dorive.coating.entity.BuildExample; import com.gitee.dorive.core.api.context.Context; -import com.gitee.dorive.core.api.executor.EntityFactory; import com.gitee.dorive.core.api.executor.Executor; -import com.gitee.dorive.core.api.executor.FieldConverter; -import com.gitee.dorive.core.entity.ExecutorResult; -import com.gitee.dorive.core.impl.factory.DefaultEntityFactory; +import com.gitee.dorive.core.entity.common.EntityStoreInfo; +import com.gitee.dorive.core.entity.option.QueryMethod; +import com.gitee.dorive.mybatis.plus.impl.MybatisPlusExecutor; +import com.gitee.dorive.query.api.QueryExecutor; +import com.gitee.dorive.query.entity.QueryContext; +import com.gitee.dorive.query.entity.QueryWrapper; import com.gitee.dorive.ref.repository.AbstractRefRepository; -import com.gitee.dorive.spring.boot.starter.impl.CountQuerier; -import com.gitee.dorive.spring.boot.starter.impl.SQLExampleBuilder; -import com.gitee.dorive.spring.boot.starter.impl.executor.MybatisPlusExecutor; +import com.gitee.dorive.sql.api.SqlRunner; +import com.gitee.dorive.sql.impl.CountQuerier; +import com.gitee.dorive.sql.impl.SegmentBuilder; +import com.gitee.dorive.sql.impl.SqlQueryExecutor; +import com.gitee.dorive.sql.impl.UnionExecutor; import lombok.Data; import lombok.EqualsAndHashCode; import org.apache.commons.lang3.StringUtils; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; +import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import java.util.stream.Collectors; @Data @EqualsAndHashCode(callSuper = false) public class MybatisPlusRepository extends AbstractRefRepository { - private ExampleBuilder sqlExampleBuilder; + private SqlRunner sqlRunner; + private QueryExecutor sqlQueryExecutor; private CountQuerier countQuerier; @Override public void afterPropertiesSet() throws Exception { + ImplFactory implFactory = getApplicationContext().getBean(ImplFactory.class); + this.sqlRunner = implFactory.getInstance(SqlRunner.class); + SegmentBuilder segmentBuilder = new SegmentBuilder(); + this.sqlQueryExecutor = new SqlQueryExecutor(this, segmentBuilder, this.sqlRunner); + this.countQuerier = new CountQuerier(this, segmentBuilder, this.sqlRunner); super.afterPropertiesSet(); - this.sqlExampleBuilder = new SQLExampleBuilder(this); - this.countQuerier = new CountQuerier(this); } @Override - @SuppressWarnings("unchecked") - protected ExecutorResult newExecutor(EntityDef entityDef, EntityEle entityEle, Map converterMap, Map attachments) { + protected EntityStoreInfo resolveEntityStoreInfo(EntityDef entityDef, EntityEle entityEle) { Class mapperClass = entityDef.getSource(); Object mapper = null; Class pojoClass = null; if (mapperClass != Object.class) { mapper = getApplicationContext().getBean(mapperClass); + Assert.notNull(mapper, "The mapper cannot be null! source: {}", mapperClass); Type[] genericInterfaces = mapperClass.getGenericInterfaces(); if (genericInterfaces.length > 0) { Type genericInterface = mapperClass.getGenericInterfaces()[0]; @@ -83,80 +89,50 @@ public class MybatisPlusRepository extends AbstractRefRepository { Assert.notNull(pojoClass, "The class of pojo cannot be null! source: {}", mapperClass); TableInfo tableInfo = TableInfoHelper.getTableInfo(pojoClass); - attachments.put(Keys.TABLE_INFO, tableInfo); - - EntityFactory entityFactory = newEntityFactory(entityDef, entityEle, pojoClass, tableInfo, converterMap); - Executor executor = new MybatisPlusExecutor(entityDef, entityEle, (BaseMapper) mapper, (Class) pojoClass); - return new ExecutorResult(entityFactory, executor); - } - - private EntityFactory newEntityFactory(EntityDef entityDef, EntityEle entityEle, Class pojoClass, TableInfo tableInfo, - Map converterMap) { - Class factoryClass = entityDef.getFactory(); - EntityFactory entityFactory; - if (factoryClass == Object.class) { - entityFactory = new DefaultEntityFactory(); - } else { - entityFactory = (EntityFactory) getApplicationContext().getBean(factoryClass); - } - if (entityFactory instanceof DefaultEntityFactory) { - DefaultEntityFactory defaultEntityFactory = (DefaultEntityFactory) entityFactory; - defaultEntityFactory.setEntityEle(entityEle); - defaultEntityFactory.setPojoClass(pojoClass); - - Map aliasFieldMapping = newAliasFieldMapping(entityEle); - defaultEntityFactory.setReCopyOptions(aliasFieldMapping, converterMap); - - Map fieldPropMapping = newFieldPropMapping(tableInfo, aliasFieldMapping); - defaultEntityFactory.setDeCopyOptions(fieldPropMapping, newPropConverterMap(fieldPropMapping, converterMap)); - } - return entityFactory; + Assert.notNull(tableInfo, "The table info cannot be null! source: {}", mapperClass); + assert tableInfo != null; + return newEntityStoreInfo(mapperClass, mapper, pojoClass, tableInfo); } - private Map newAliasFieldMapping(EntityEle entityEle) { - Map fieldAliasMap = entityEle.getFieldAliasMap(); - return fieldAliasMap.entrySet().stream().collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey)); - } - - private Map newFieldPropMapping(TableInfo tableInfo, Map aliasFieldMapping) { - String keyColumn = tableInfo.getKeyColumn(); + private EntityStoreInfo newEntityStoreInfo(Class mapperClass, Object mapper, Class pojoClass, TableInfo tableInfo) { + String tableName = tableInfo.getTableName(); String keyProperty = tableInfo.getKeyProperty(); + String keyColumn = tableInfo.getKeyColumn(); List tableFieldInfos = tableInfo.getFieldList(); - Map fieldPropMapping = new LinkedHashMap<>(); + int size = tableFieldInfos.size() + 1; - if (StringUtils.isNotBlank(keyColumn) && StringUtils.isNotBlank(keyProperty)) { - String field = aliasFieldMapping.get(keyColumn); - if (field != null) { - fieldPropMapping.put(field, keyProperty); - } - } + Map propAliasMappingWithoutPk = new LinkedHashMap<>(size * 4 / 3 + 1); for (TableFieldInfo tableFieldInfo : tableFieldInfos) { - String field = aliasFieldMapping.get(tableFieldInfo.getColumn()); - if (field != null) { - fieldPropMapping.put(field, tableFieldInfo.getProperty()); - } + propAliasMappingWithoutPk.put(tableFieldInfo.getProperty(), tableFieldInfo.getColumn()); } - return fieldPropMapping; + + Map propAliasMapping = new LinkedHashMap<>(size * 4 / 3 + 1); + if (StringUtils.isNotBlank(keyProperty) && StringUtils.isNotBlank(keyColumn)) { + propAliasMapping.put(keyProperty, keyColumn); + } + propAliasMapping.putAll(propAliasMappingWithoutPk); + + List columns = new ArrayList<>(propAliasMapping.values()); + String selectColumns = StrUtil.join(",", columns); + + return new EntityStoreInfo(mapperClass, mapper, pojoClass, + tableName, keyProperty, keyColumn, propAliasMappingWithoutPk, propAliasMapping, selectColumns); } - private Map newPropConverterMap(Map fieldPropMapping, Map converterMap) { - Map propConverterMap = new LinkedHashMap<>(converterMap.size()); - converterMap.forEach((field, fieldConverter) -> { - String prop = fieldPropMapping.get(field); - propConverterMap.put(prop, fieldConverter); - }); - return propConverterMap; + @Override + protected Executor newExecutor(EntityDef entityDef, EntityEle entityEle, EntityStoreInfo entityStoreInfo) { + Executor executor = new MybatisPlusExecutor(entityDef, entityEle, entityStoreInfo); + return new UnionExecutor(executor, sqlRunner, entityStoreInfo); } @Override - public BuildExample buildExample(Context context, Object coating) { - Map attachments = context.getAttachments(); - String querier = (String) attachments.get(Keys.QUERIER); - if (querier == null || "SQL".equals(querier)) { - return sqlExampleBuilder.buildExample(context, coating); - } else { - return getExampleBuilder().buildExample(context, coating); + protected QueryExecutor adaptiveQueryExecutor(QueryContext queryContext, QueryWrapper queryWrapper) { + Context context = queryContext.getContext(); + QueryMethod queryMethod = (QueryMethod) context.getOption(QueryMethod.class); + if (queryMethod == null || queryMethod == QueryMethod.SQL) { + return sqlQueryExecutor; } + return super.adaptiveQueryExecutor(queryContext, queryWrapper); } } diff --git a/dorive-event/src/main/java/com/gitee/dorive/event/api/EntityListener.java b/dorive-mybatis-plus/src/main/java/com/gitee/dorive/mybatis/plus/util/LambdaUtils.java similarity index 62% rename from dorive-event/src/main/java/com/gitee/dorive/event/api/EntityListener.java rename to dorive-mybatis-plus/src/main/java/com/gitee/dorive/mybatis/plus/util/LambdaUtils.java index 1b64270ea5ac16305c955a9f0734f2f3edb0873c..e1fe8f1dcbf29643f33696ebd9b35cc72d06de78 100644 --- a/dorive-event/src/main/java/com/gitee/dorive/event/api/EntityListener.java +++ b/dorive-mybatis-plus/src/main/java/com/gitee/dorive/mybatis/plus/util/LambdaUtils.java @@ -15,19 +15,17 @@ * limitations under the License. */ -package com.gitee.dorive.event.api; +package com.gitee.dorive.mybatis.plus.util; -import com.gitee.dorive.event.annotation.Listener; -import com.gitee.dorive.event.entity.ExecutorEvent; -import org.springframework.core.annotation.AnnotationUtils; +import com.baomidou.mybatisplus.core.toolkit.support.LambdaMeta; +import com.baomidou.mybatisplus.core.toolkit.support.SFunction; +import org.apache.ibatis.reflection.property.PropertyNamer; -public interface EntityListener { +public class LambdaUtils { - default Class subscribe() { - Listener listener = AnnotationUtils.getAnnotation(this.getClass(), Listener.class); - return listener != null ? listener.value() : null; + public static String toProperty(SFunction function) { + LambdaMeta meta = com.baomidou.mybatisplus.core.toolkit.LambdaUtils.extract(function); + return PropertyNamer.methodToProperty(meta.getImplMethodName()); } - void onApplicationEvent(ExecutorEvent executorEvent); - } diff --git a/dorive-spring-boot-starter/src/main/resources/META-INF/spring.factories b/dorive-mybatis-plus/src/main/resources/META-INF/spring.factories similarity index 37% rename from dorive-spring-boot-starter/src/main/resources/META-INF/spring.factories rename to dorive-mybatis-plus/src/main/resources/META-INF/spring.factories index 094855eb4092637fc99327c324339cf616d16029..4a1f7850cf0b355c6eb7fd8786a339f196c50e98 100644 --- a/dorive-spring-boot-starter/src/main/resources/META-INF/spring.factories +++ b/dorive-mybatis-plus/src/main/resources/META-INF/spring.factories @@ -1,4 +1,5 @@ org.springframework.boot.env.EnvironmentPostProcessor=\ - com.gitee.dorive.spring.boot.starter.config.MybatisPlusConfiguration + com.gitee.dorive.mybatis.plus.config.MybatisPlusConfiguration org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ - com.gitee.dorive.spring.boot.starter.config.MybatisPlusConfiguration + com.gitee.dorive.mybatis.plus.config.MybatisPlusConfiguration,\ + com.gitee.dorive.mybatis.plus.config.DoriveMybatisPlusConfiguration diff --git a/dorive-mybatis-plus/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/dorive-mybatis-plus/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 0000000000000000000000000000000000000000..b42b656d11ffda8038bdf474fc9d2232f7467f7a --- /dev/null +++ b/dorive-mybatis-plus/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1,2 @@ +com.gitee.dorive.mybatis.plus.config.MybatisPlusConfiguration +com.gitee.dorive.mybatis.plus.config.DoriveStarterConfiguration \ No newline at end of file diff --git a/dorive-proxy/pom.xml b/dorive-proxy/pom.xml index c292e6c408fb18f2f7273d505e78c21fb8f7a39f..162bdd4ce846f60beb42290e95b42fc8028dcbfb 100644 --- a/dorive-proxy/pom.xml +++ b/dorive-proxy/pom.xml @@ -6,7 +6,7 @@ com.gitee.digital-engine dorive - 3.4.3.1 + 3.4.3.3 dorive-proxy diff --git a/dorive-coating/pom.xml b/dorive-query/pom.xml similarity index 89% rename from dorive-coating/pom.xml rename to dorive-query/pom.xml index cd0dd2e769284e0f5f64d41cfb825fcd1277adf1..032a77afcebae3332e2035e2b683b34c4f20fb36 100644 --- a/dorive-coating/pom.xml +++ b/dorive-query/pom.xml @@ -6,9 +6,9 @@ com.gitee.digital-engine dorive - 3.4.3.1 + 3.4.3.3 - dorive-coating + dorive-query com.gitee.digital-engine diff --git a/dorive-coating/src/main/java/com/gitee/dorive/coating/annotation/Criterion.java b/dorive-query/src/main/java/com/gitee/dorive/query/annotation/Criterion.java similarity index 96% rename from dorive-coating/src/main/java/com/gitee/dorive/coating/annotation/Criterion.java rename to dorive-query/src/main/java/com/gitee/dorive/query/annotation/Criterion.java index 7563ff9900631b68fcbd240a7d70bfbc42f54d99..4f182a2676f5e6d4246c8c3ebada83c802fab3cc 100644 --- a/dorive-coating/src/main/java/com/gitee/dorive/coating/annotation/Criterion.java +++ b/dorive-query/src/main/java/com/gitee/dorive/query/annotation/Criterion.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package com.gitee.dorive.coating.annotation; +package com.gitee.dorive.query.annotation; import org.springframework.core.annotation.AliasFor; diff --git a/dorive-coating/src/main/java/com/gitee/dorive/coating/annotation/Example.java b/dorive-query/src/main/java/com/gitee/dorive/query/annotation/Example.java similarity index 96% rename from dorive-coating/src/main/java/com/gitee/dorive/coating/annotation/Example.java rename to dorive-query/src/main/java/com/gitee/dorive/query/annotation/Example.java index 4bbe1677513de759e64284dca78df5b99727f71f..4ecc2b8fdca03c514fc8db469e7c1962c687426c 100644 --- a/dorive-coating/src/main/java/com/gitee/dorive/coating/annotation/Example.java +++ b/dorive-query/src/main/java/com/gitee/dorive/query/annotation/Example.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package com.gitee.dorive.coating.annotation; +package com.gitee.dorive.query.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; diff --git a/dorive-coating/src/main/java/com/gitee/dorive/coating/annotation/CoatingScan.java b/dorive-query/src/main/java/com/gitee/dorive/query/annotation/QueryScan.java similarity index 94% rename from dorive-coating/src/main/java/com/gitee/dorive/coating/annotation/CoatingScan.java rename to dorive-query/src/main/java/com/gitee/dorive/query/annotation/QueryScan.java index 8c1c8c5a7d43e243ac8b2797f3feb4383501d3e9..4a3a376ace670be9cb884632e2a8c4b93d201273 100644 --- a/dorive-coating/src/main/java/com/gitee/dorive/coating/annotation/CoatingScan.java +++ b/dorive-query/src/main/java/com/gitee/dorive/query/annotation/QueryScan.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package com.gitee.dorive.coating.annotation; +package com.gitee.dorive.query.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; @@ -28,7 +28,7 @@ import java.lang.annotation.Target; @Documented @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) -public @interface CoatingScan { +public @interface QueryScan { String[] value() default {}; diff --git a/dorive-query/src/main/java/com/gitee/dorive/query/api/QueryExecutor.java b/dorive-query/src/main/java/com/gitee/dorive/query/api/QueryExecutor.java new file mode 100644 index 0000000000000000000000000000000000000000..d49a4f3b8a2ea83d361f55edd73a1a37923092c7 --- /dev/null +++ b/dorive-query/src/main/java/com/gitee/dorive/query/api/QueryExecutor.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.gitee.dorive.query.api; + +import com.gitee.dorive.core.entity.executor.Result; +import com.gitee.dorive.query.entity.QueryContext; +import com.gitee.dorive.query.entity.QueryWrapper; + +public interface QueryExecutor { + + Result executeQuery(QueryContext queryContext, QueryWrapper queryWrapper); + +} diff --git a/dorive-coating/src/main/java/com/gitee/dorive/coating/api/CoatingRepository.java b/dorive-query/src/main/java/com/gitee/dorive/query/api/QueryRepository.java similarity index 73% rename from dorive-coating/src/main/java/com/gitee/dorive/coating/api/CoatingRepository.java rename to dorive-query/src/main/java/com/gitee/dorive/query/api/QueryRepository.java index f9fe1fe12a605ce9590ddcf755a124faa77de208..beb67a4529fcb353773b699543294e11ebe88cf7 100644 --- a/dorive-coating/src/main/java/com/gitee/dorive/coating/api/CoatingRepository.java +++ b/dorive-query/src/main/java/com/gitee/dorive/query/api/QueryRepository.java @@ -15,18 +15,20 @@ * limitations under the License. */ -package com.gitee.dorive.coating.api; +package com.gitee.dorive.query.api; -import com.gitee.dorive.core.api.context.Context; +import com.gitee.dorive.core.api.context.Options; import com.gitee.dorive.core.api.repository.ListableRepository; import com.gitee.dorive.core.entity.executor.Page; import java.util.List; -public interface CoatingRepository extends ListableRepository { +public interface QueryRepository extends ListableRepository { - List selectByCoating(Context context, Object coating); + List selectByQuery(Options options, Object query); - Page selectPageByCoating(Context context, Object coating); + Page selectPageByQuery(Options options, Object query); + + long selectCountByQuery(Options options, Object query); } diff --git a/dorive-query/src/main/java/com/gitee/dorive/query/constant/OperatorV2.java b/dorive-query/src/main/java/com/gitee/dorive/query/constant/OperatorV2.java new file mode 100644 index 0000000000000000000000000000000000000000..fafe4bdf3db4a72c0f6e7eeda4feb8cce07b51a5 --- /dev/null +++ b/dorive-query/src/main/java/com/gitee/dorive/query/constant/OperatorV2.java @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.gitee.dorive.query.constant; + +public interface OperatorV2 { + String NULL_SWITCH = "NULL_SWITCH"; +} diff --git a/dorive-coating/src/main/java/com/gitee/dorive/coating/entity/MergedRepository.java b/dorive-query/src/main/java/com/gitee/dorive/query/entity/MergedRepository.java similarity index 97% rename from dorive-coating/src/main/java/com/gitee/dorive/coating/entity/MergedRepository.java rename to dorive-query/src/main/java/com/gitee/dorive/query/entity/MergedRepository.java index 05ce86d9503b34ad8482b004d905f774c346a72b..a4c107f80662ffa3bbdf5ea3dd442912e421b0b5 100644 --- a/dorive-coating/src/main/java/com/gitee/dorive/coating/entity/MergedRepository.java +++ b/dorive-query/src/main/java/com/gitee/dorive/query/entity/MergedRepository.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package com.gitee.dorive.coating.entity; +package com.gitee.dorive.query.entity; import com.gitee.dorive.core.impl.binder.PropertyBinder; import com.gitee.dorive.core.repository.CommonRepository; @@ -31,10 +31,10 @@ public class MergedRepository { private String lastAccessPath; private String absoluteAccessPath; + private String relativeAccessPath; + private boolean merged; private CommonRepository definedRepository; private Map> mergedBindersMap; - private boolean merged; - private String relativeAccessPath; private CommonRepository executedRepository; private Integer order; diff --git a/dorive-query/src/main/java/com/gitee/dorive/query/entity/QueryContext.java b/dorive-query/src/main/java/com/gitee/dorive/query/entity/QueryContext.java new file mode 100644 index 0000000000000000000000000000000000000000..7d45606794463c56b06776d3c28b2a7edbd306ba --- /dev/null +++ b/dorive-query/src/main/java/com/gitee/dorive/query/entity/QueryContext.java @@ -0,0 +1,65 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.gitee.dorive.query.entity; + +import com.gitee.dorive.core.api.context.Context; +import com.gitee.dorive.core.entity.executor.Example; +import com.gitee.dorive.core.entity.executor.Result; +import com.gitee.dorive.query.entity.enums.ResultType; +import com.gitee.dorive.query.impl.resolver.QueryResolver; +import lombok.Data; + +import java.util.Collections; +import java.util.Map; + +@Data +public class QueryContext { + + private Context context; + private ResultType resultType; + private QueryResolver queryResolver; + private Map exampleMap; + private Example example; + + public QueryContext(Context context, ResultType resultType) { + this.context = context; + this.resultType = resultType; + } + + public boolean isSimpleQuery() { + return exampleMap.size() == 1 && exampleMap.containsKey("/"); + } + + public boolean isNeedCount() { + return resultType == ResultType.COUNT_AND_DATA || resultType == ResultType.COUNT; + } + + public Result newEmptyResult() { + if (resultType == ResultType.COUNT_AND_DATA) { + return new Result<>(example.getPage()); + + } else if (resultType == ResultType.DATA) { + return new Result<>(Collections.emptyList()); + + } else if (resultType == ResultType.COUNT) { + return new Result<>(0L); + } + throw new RuntimeException("Unsupported type!"); + } + +} diff --git a/dorive-coating/src/main/java/com/gitee/dorive/coating/entity/CoatingField.java b/dorive-query/src/main/java/com/gitee/dorive/query/entity/QueryField.java similarity index 92% rename from dorive-coating/src/main/java/com/gitee/dorive/coating/entity/CoatingField.java rename to dorive-query/src/main/java/com/gitee/dorive/query/entity/QueryField.java index 898e8b37666dd2082140a8f4a6d04b30361108c7..6614660558aae0dd522a36f79628111be3f6fb52 100644 --- a/dorive-coating/src/main/java/com/gitee/dorive/coating/entity/CoatingField.java +++ b/dorive-query/src/main/java/com/gitee/dorive/query/entity/QueryField.java @@ -15,10 +15,10 @@ * limitations under the License. */ -package com.gitee.dorive.coating.entity; +package com.gitee.dorive.query.entity; import cn.hutool.core.util.ReflectUtil; -import com.gitee.dorive.coating.entity.def.CriterionDef; +import com.gitee.dorive.query.entity.def.CriterionDef; import lombok.AllArgsConstructor; import lombok.Data; @@ -29,7 +29,7 @@ import java.util.Collection; @Data @AllArgsConstructor -public class CoatingField { +public class QueryField { private Field field; private Class type; @@ -38,7 +38,7 @@ public class CoatingField { private String name; private CriterionDef criterionDef; - public CoatingField(Field field) { + public QueryField(Field field) { this.field = field; this.type = field.getType(); this.collection = false; diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/entity/ExecutorResult.java b/dorive-query/src/main/java/com/gitee/dorive/query/entity/QueryWrapper.java similarity index 78% rename from dorive-core/src/main/java/com/gitee/dorive/core/entity/ExecutorResult.java rename to dorive-query/src/main/java/com/gitee/dorive/query/entity/QueryWrapper.java index 2e9e41b5dd1670c5aa17b59a8d98fc15a30ba22c..3d01c608938d97cf9e381fd0abfdd41ed29b5dba 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/entity/ExecutorResult.java +++ b/dorive-query/src/main/java/com/gitee/dorive/query/entity/QueryWrapper.java @@ -15,16 +15,13 @@ * limitations under the License. */ -package com.gitee.dorive.core.entity; +package com.gitee.dorive.query.entity; -import com.gitee.dorive.core.api.executor.EntityFactory; -import com.gitee.dorive.core.api.executor.Executor; import lombok.AllArgsConstructor; import lombok.Data; @Data @AllArgsConstructor -public class ExecutorResult { - private EntityFactory entityFactory; - private Executor executor; +public class QueryWrapper { + private Object query; } diff --git a/dorive-coating/src/main/java/com/gitee/dorive/coating/entity/SpecificFields.java b/dorive-query/src/main/java/com/gitee/dorive/query/entity/SpecificFields.java similarity index 73% rename from dorive-coating/src/main/java/com/gitee/dorive/coating/entity/SpecificFields.java rename to dorive-query/src/main/java/com/gitee/dorive/query/entity/SpecificFields.java index 2e393137416836376866ccb5665548b1005908a1..c77d1a5dd827abbc07783cdf38d9c8e19216c304 100644 --- a/dorive-coating/src/main/java/com/gitee/dorive/coating/entity/SpecificFields.java +++ b/dorive-query/src/main/java/com/gitee/dorive/query/entity/SpecificFields.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package com.gitee.dorive.coating.entity; +package com.gitee.dorive.query.entity; import cn.hutool.core.convert.Convert; import com.gitee.dorive.api.constant.Order; @@ -29,36 +29,36 @@ import java.util.List; @Data public class SpecificFields { - private CoatingField sortByField; - private CoatingField orderField; - private CoatingField pageField; - private CoatingField limitField; + private QueryField sortByField; + private QueryField orderField; + private QueryField pageField; + private QueryField limitField; - public boolean tryAddField(CoatingField coatingField) { - String fieldName = coatingField.getName(); + public boolean tryAddField(QueryField queryField) { + String fieldName = queryField.getName(); if ("sortBy".equals(fieldName)) { - sortByField = coatingField; + sortByField = queryField; return true; } else if ("order".equals(fieldName)) { - orderField = coatingField; + orderField = queryField; return true; } else if ("page".equals(fieldName)) { - pageField = coatingField; + pageField = queryField; return true; } else if ("limit".equals(fieldName)) { - limitField = coatingField; + limitField = queryField; return true; } return false; } - public OrderBy newOrderBy(Object coating) { + public OrderBy newOrderBy(Object query) { if (sortByField != null && orderField != null) { - Object sortBy = sortByField.getFieldValue(coating); - Object order = orderField.getFieldValue(coating); + Object sortBy = sortByField.getFieldValue(query); + Object order = orderField.getFieldValue(query); if (sortBy != null && order instanceof String) { List properties = StringUtils.toList(sortBy); if (properties != null && !properties.isEmpty()) { @@ -72,10 +72,10 @@ public class SpecificFields { return null; } - public Page newPage(Object coating) { + public Page newPage(Object query) { if (pageField != null && limitField != null) { - Object page = pageField.getFieldValue(coating); - Object limit = limitField.getFieldValue(coating); + Object page = pageField.getFieldValue(query); + Object limit = limitField.getFieldValue(query); if (page != null && limit != null) { return new Page<>(Convert.convert(Long.class, page), Convert.convert(Long.class, limit)); } diff --git a/dorive-coating/src/main/java/com/gitee/dorive/coating/entity/def/CriterionDef.java b/dorive-query/src/main/java/com/gitee/dorive/query/entity/def/CriterionDef.java similarity index 94% rename from dorive-coating/src/main/java/com/gitee/dorive/coating/entity/def/CriterionDef.java rename to dorive-query/src/main/java/com/gitee/dorive/query/entity/def/CriterionDef.java index 220a49c03cdd7151f35821c849294f7d8c571249..b817be6e6c18cd46dfdae8ea0d31766496c53ca2 100644 --- a/dorive-coating/src/main/java/com/gitee/dorive/coating/entity/def/CriterionDef.java +++ b/dorive-query/src/main/java/com/gitee/dorive/query/entity/def/CriterionDef.java @@ -15,10 +15,10 @@ * limitations under the License. */ -package com.gitee.dorive.coating.entity.def; +package com.gitee.dorive.query.entity.def; import cn.hutool.core.bean.BeanUtil; -import com.gitee.dorive.coating.annotation.Criterion; +import com.gitee.dorive.query.annotation.Criterion; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; diff --git a/dorive-coating/src/main/java/com/gitee/dorive/coating/entity/def/ExampleDef.java b/dorive-query/src/main/java/com/gitee/dorive/query/entity/def/ExampleDef.java similarity index 93% rename from dorive-coating/src/main/java/com/gitee/dorive/coating/entity/def/ExampleDef.java rename to dorive-query/src/main/java/com/gitee/dorive/query/entity/def/ExampleDef.java index 6970a7dcd9ce3e6c98ef0299bb01583c7ed81677..0f0ad3cc1914b9c6ab9d5e843f5b1c46290876f9 100644 --- a/dorive-coating/src/main/java/com/gitee/dorive/coating/entity/def/ExampleDef.java +++ b/dorive-query/src/main/java/com/gitee/dorive/query/entity/def/ExampleDef.java @@ -15,10 +15,10 @@ * limitations under the License. */ -package com.gitee.dorive.coating.entity.def; +package com.gitee.dorive.query.entity.def; import cn.hutool.core.bean.BeanUtil; -import com.gitee.dorive.coating.annotation.Example; +import com.gitee.dorive.query.annotation.Example; import org.springframework.core.annotation.AnnotatedElementUtils; import java.lang.reflect.AnnotatedElement; diff --git a/dorive-coating/src/main/java/com/gitee/dorive/coating/entity/def/CoatingScanDef.java b/dorive-query/src/main/java/com/gitee/dorive/query/entity/def/QueryScanDef.java similarity index 81% rename from dorive-coating/src/main/java/com/gitee/dorive/coating/entity/def/CoatingScanDef.java rename to dorive-query/src/main/java/com/gitee/dorive/query/entity/def/QueryScanDef.java index 05d9ff044109ac14094fe0fdb417e6bede8035c5..a3838549937ba08d0fc94560aa6bd1916659ba9f 100644 --- a/dorive-coating/src/main/java/com/gitee/dorive/coating/entity/def/CoatingScanDef.java +++ b/dorive-query/src/main/java/com/gitee/dorive/query/entity/def/QueryScanDef.java @@ -15,10 +15,10 @@ * limitations under the License. */ -package com.gitee.dorive.coating.entity.def; +package com.gitee.dorive.query.entity.def; import cn.hutool.core.bean.BeanUtil; -import com.gitee.dorive.coating.annotation.CoatingScan; +import com.gitee.dorive.query.annotation.QueryScan; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @@ -30,15 +30,15 @@ import java.util.Map; @Data @NoArgsConstructor @AllArgsConstructor -public class CoatingScanDef { +public class QueryScanDef { private String[] value; private String regex; private Class[] queries; - public static CoatingScanDef fromElement(AnnotatedElement element) { - Map attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(element, CoatingScan.class); - return attributes != null ? BeanUtil.copyProperties(attributes, CoatingScanDef.class) : null; + public static QueryScanDef fromElement(AnnotatedElement element) { + Map attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(element, QueryScan.class); + return attributes != null ? BeanUtil.copyProperties(attributes, QueryScanDef.class) : null; } } diff --git a/dorive-query/src/main/java/com/gitee/dorive/query/entity/enums/ResultType.java b/dorive-query/src/main/java/com/gitee/dorive/query/entity/enums/ResultType.java new file mode 100644 index 0000000000000000000000000000000000000000..0329d0d1e244860c6be385d9740bce77b5b8a2c1 --- /dev/null +++ b/dorive-query/src/main/java/com/gitee/dorive/query/entity/enums/ResultType.java @@ -0,0 +1,24 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.gitee.dorive.query.entity.enums; + +public enum ResultType { + COUNT_AND_DATA, + DATA, + COUNT +} diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/repository/AbstractExampleRepository.java b/dorive-query/src/main/java/com/gitee/dorive/query/impl/executor/AbstractQueryExecutor.java similarity index 38% rename from dorive-core/src/main/java/com/gitee/dorive/core/repository/AbstractExampleRepository.java rename to dorive-query/src/main/java/com/gitee/dorive/query/impl/executor/AbstractQueryExecutor.java index 310af10f1345028865b28fc7b5b01c2e8a28eb7d..13e2e620db26fefab22e4f260ee9f9c3f0f962ee 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/repository/AbstractExampleRepository.java +++ b/dorive-query/src/main/java/com/gitee/dorive/query/impl/executor/AbstractQueryExecutor.java @@ -15,60 +15,47 @@ * limitations under the License. */ -package com.gitee.dorive.core.repository; +package com.gitee.dorive.query.impl.executor; import com.gitee.dorive.core.api.context.Context; import com.gitee.dorive.core.entity.executor.Example; -import com.gitee.dorive.core.entity.executor.InnerExample; import com.gitee.dorive.core.entity.executor.Page; -import com.gitee.dorive.core.util.ExampleUtils; -import lombok.Data; -import lombok.EqualsAndHashCode; +import com.gitee.dorive.core.entity.executor.Result; +import com.gitee.dorive.query.api.QueryExecutor; +import com.gitee.dorive.query.entity.QueryContext; +import com.gitee.dorive.query.entity.QueryWrapper; +import com.gitee.dorive.query.entity.enums.ResultType; +import com.gitee.dorive.query.repository.AbstractQueryRepository; import java.util.List; -@Data -@EqualsAndHashCode(callSuper = false) -public abstract class AbstractExampleRepository extends AbstractGenericRepository { +public abstract class AbstractQueryExecutor implements QueryExecutor { - @Override - public List selectByExample(Context context, Example example) { - if (!(example instanceof InnerExample)) { - example = ExampleUtils.tryClone(example); - } - return super.selectByExample(context, example); - } - - @Override - public Page selectPageByExample(Context context, Example example) { - if (!(example instanceof InnerExample)) { - example = ExampleUtils.tryClone(example); - } - return super.selectPageByExample(context, example); - } + protected final AbstractQueryRepository repository; - @Override - public long selectCount(Context context, Example example) { - if (!(example instanceof InnerExample)) { - example = ExampleUtils.tryClone(example); - } - return super.selectCount(context, example); - } - - @Override - public int updateByExample(Context context, Object entity, Example example) { - if (!(example instanceof InnerExample)) { - example = ExampleUtils.tryClone(example); - } - return super.updateByExample(context, entity, example); + public AbstractQueryExecutor(AbstractQueryRepository repository) { + this.repository = repository; } @Override - public int deleteByExample(Context context, Example example) { - if (!(example instanceof InnerExample)) { - example = ExampleUtils.tryClone(example); + @SuppressWarnings("unchecked") + public Result executeQuery(QueryContext queryContext, QueryWrapper queryWrapper) { + Context context = queryContext.getContext(); + ResultType resultType = queryContext.getResultType(); + Example example = queryContext.getExample(); + if (resultType == ResultType.COUNT_AND_DATA) { + Page page = (Page) repository.selectPageByExample(context, example); + return new Result<>(page); + + } else if (resultType == ResultType.DATA) { + List entities = (List) repository.selectByExample(context, example); + return new Result<>(entities); + + } else if (resultType == ResultType.COUNT) { + long count = repository.selectCountByExample(context, example); + return new Result<>(count); } - return super.deleteByExample(context, example); + return queryContext.newEmptyResult(); } } diff --git a/dorive-query/src/main/java/com/gitee/dorive/query/impl/executor/SimpleQueryExecutor.java b/dorive-query/src/main/java/com/gitee/dorive/query/impl/executor/SimpleQueryExecutor.java new file mode 100644 index 0000000000000000000000000000000000000000..34088a98eaec90dd9a955a1f7a95d0b886e1ec15 --- /dev/null +++ b/dorive-query/src/main/java/com/gitee/dorive/query/impl/executor/SimpleQueryExecutor.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.gitee.dorive.query.impl.executor; + +import com.gitee.dorive.query.repository.AbstractQueryRepository; + +public class SimpleQueryExecutor extends AbstractQueryExecutor { + + public SimpleQueryExecutor(AbstractQueryRepository repository) { + super(repository); + } + +} diff --git a/dorive-coating/src/main/java/com/gitee/dorive/coating/impl/DefaultExampleBuilder.java b/dorive-query/src/main/java/com/gitee/dorive/query/impl/executor/StepwiseQueryExecutor.java similarity index 54% rename from dorive-coating/src/main/java/com/gitee/dorive/coating/impl/DefaultExampleBuilder.java rename to dorive-query/src/main/java/com/gitee/dorive/query/impl/executor/StepwiseQueryExecutor.java index 76fb485566b43d6af12b84d31216b63e309ca14a..7654af28bd364dde1d5e3ec8aa213c264c9a5973 100644 --- a/dorive-coating/src/main/java/com/gitee/dorive/coating/impl/DefaultExampleBuilder.java +++ b/dorive-query/src/main/java/com/gitee/dorive/query/impl/executor/StepwiseQueryExecutor.java @@ -15,75 +15,70 @@ * limitations under the License. */ -package com.gitee.dorive.coating.impl; - -import cn.hutool.core.lang.Assert; -import com.gitee.dorive.coating.api.ExampleBuilder; -import com.gitee.dorive.coating.entity.BuildExample; -import com.gitee.dorive.coating.entity.CoatingCriteria; -import com.gitee.dorive.coating.entity.CoatingType; -import com.gitee.dorive.coating.entity.MergedRepository; -import com.gitee.dorive.coating.repository.AbstractCoatingRepository; +package com.gitee.dorive.query.impl.executor; + import com.gitee.dorive.core.api.context.Context; -import com.gitee.dorive.core.entity.executor.Criterion; -import com.gitee.dorive.core.entity.executor.MultiInBuilder; -import com.gitee.dorive.core.entity.executor.OrderBy; -import com.gitee.dorive.core.entity.executor.Page; +import com.gitee.dorive.core.entity.executor.Example; +import com.gitee.dorive.core.entity.executor.InnerExample; +import com.gitee.dorive.core.entity.executor.Result; import com.gitee.dorive.core.impl.binder.PropertyBinder; import com.gitee.dorive.core.impl.resolver.BinderResolver; import com.gitee.dorive.core.repository.CommonRepository; +import com.gitee.dorive.core.util.MultiInBuilder; +import com.gitee.dorive.query.entity.MergedRepository; +import com.gitee.dorive.query.entity.QueryContext; +import com.gitee.dorive.query.entity.QueryWrapper; +import com.gitee.dorive.query.impl.resolver.QueryResolver; +import com.gitee.dorive.query.repository.AbstractQueryRepository; import lombok.AllArgsConstructor; import lombok.Data; -import java.util.ArrayList; import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; -public class DefaultExampleBuilder implements ExampleBuilder { - - private final AbstractCoatingRepository repository; +public class StepwiseQueryExecutor extends AbstractQueryExecutor { - public DefaultExampleBuilder(AbstractCoatingRepository repository) { - this.repository = repository; + public StepwiseQueryExecutor(AbstractQueryRepository repository) { + super(repository); } @Override - public BuildExample buildExample(Context context, Object coating) { - CoatingType coatingType = repository.getCoatingType(coating); - CoatingCriteria coatingCriteria = coatingType.newCriteria(coating); - Map> criteriaMap = coatingCriteria.getCriteriaMap(); - OrderBy orderBy = coatingCriteria.getOrderBy(); - Page page = coatingCriteria.getPage(); - - Map repoExampleMap = new LinkedHashMap<>(); - for (MergedRepository mergedRepository : coatingType.getReversedMergedRepositories()) { + public Result executeQuery(QueryContext queryContext, QueryWrapper queryWrapper) { + Map exampleWrapperMap = buildExampleWrapperMap(queryContext); + executeQuery(queryContext, exampleWrapperMap); + ExampleWrapper exampleWrapper = exampleWrapperMap.get("/"); + boolean abandoned = exampleWrapper.isAbandoned(); + if (abandoned) { + return queryContext.newEmptyResult(); + } + return super.executeQuery(queryContext, queryWrapper); + } + + private Map buildExampleWrapperMap(QueryContext queryContext) { + QueryResolver queryResolver = queryContext.getQueryResolver(); + Map exampleMap = queryContext.getExampleMap(); + Map exampleWrapperMap = new LinkedHashMap<>(); + for (MergedRepository mergedRepository : queryResolver.getReversedMergedRepositories()) { String absoluteAccessPath = mergedRepository.getAbsoluteAccessPath(); String relativeAccessPath = mergedRepository.getRelativeAccessPath(); - List criteria = criteriaMap.computeIfAbsent(absoluteAccessPath, key -> new ArrayList<>(2)); - BuildExample buildExample = new BuildExample(criteria); - repoExampleMap.put(relativeAccessPath, new RepoExample(mergedRepository, buildExample)); + Example example = exampleMap.computeIfAbsent(absoluteAccessPath, key -> new InnerExample()); + ExampleWrapper exampleWrapper = new ExampleWrapper(mergedRepository, example, false); + exampleWrapperMap.put(relativeAccessPath, exampleWrapper); } - - executeQuery(context, repoExampleMap); - - RepoExample repoExample = repoExampleMap.get("/"); - Assert.notNull(repoExample, "The criterion cannot be null!"); - - BuildExample buildExample = repoExample.getBuildExample(); - buildExample.setOrderBy(orderBy); - buildExample.setPage(page); - return buildExample; + return exampleWrapperMap; } - private void executeQuery(Context context, Map repoExampleMap) { - repoExampleMap.forEach((accessPath, repoExample) -> { + private void executeQuery(QueryContext queryContext, Map exampleWrapperMap) { + Context context = queryContext.getContext(); + exampleWrapperMap.forEach((accessPath, exampleWrapper) -> { if ("/".equals(accessPath)) return; - MergedRepository mergedRepository = repoExample.getMergedRepository(); - BuildExample buildExample = repoExample.getBuildExample(); + MergedRepository mergedRepository = exampleWrapper.getMergedRepository(); + Example example = exampleWrapper.getExample(); + boolean abandoned = exampleWrapper.isAbandoned(); CommonRepository definedRepository = mergedRepository.getDefinedRepository(); Map> mergedBindersMap = mergedRepository.getMergedBindersMap(); @@ -92,36 +87,37 @@ public class DefaultExampleBuilder implements ExampleBuilder { BinderResolver binderResolver = definedRepository.getBinderResolver(); for (String relativeAccessPath : mergedBindersMap.keySet()) { - RepoExample targetRepoExample = repoExampleMap.get(relativeAccessPath); - if (targetRepoExample != null) { - BuildExample targetExample = targetRepoExample.getBuildExample(); - if (targetExample.isAbandoned()) { - buildExample.setAbandoned(true); + ExampleWrapper targetExampleWrapper = exampleWrapperMap.get(relativeAccessPath); + if (targetExampleWrapper != null) { + if (targetExampleWrapper.isAbandoned()) { + abandoned = true; break; } } } - if (buildExample.isQueryAll()) { - return; - } + List entities; + if (abandoned) { + entities = Collections.emptyList(); + + } else if (example.isNotEmpty()) { + example.select(binderResolver.getSelfFields()); + entities = executedRepository.selectByExample(context, example); - List entities = Collections.emptyList(); - if (!buildExample.isAbandoned() && buildExample.isNotEmpty()) { - buildExample.select(binderResolver.getSelfFields()); - entities = executedRepository.selectByExample(context, buildExample); + } else { + return; } for (Map.Entry> entry : mergedBindersMap.entrySet()) { String relativeAccessPath = entry.getKey(); List binders = entry.getValue(); - RepoExample targetRepoExample = repoExampleMap.get(relativeAccessPath); - if (targetRepoExample != null) { - BuildExample targetExample = targetRepoExample.getBuildExample(); + ExampleWrapper targetExampleWrapper = exampleWrapperMap.get(relativeAccessPath); + if (targetExampleWrapper != null) { if (entities.isEmpty()) { - targetExample.setAbandoned(true); + targetExampleWrapper.setAbandoned(true); return; } + Example targetExample = targetExampleWrapper.getExample(); if (binders.size() == 1) { PropertyBinder binder = binders.get(0); List fieldValues = binder.collectFieldValues(context, entities); @@ -133,17 +129,17 @@ public class DefaultExampleBuilder implements ExampleBuilder { targetExample.in(boundName, fieldValues); } } else { - targetExample.setAbandoned(true); + targetExampleWrapper.setAbandoned(true); } } else { List aliases = binders.stream().map(PropertyBinder::getBindAlias).collect(Collectors.toList()); - MultiInBuilder builder = new MultiInBuilder(entities.size(), aliases); + MultiInBuilder builder = new MultiInBuilder(aliases, entities.size()); collectFieldValues(context, entities, binders, builder); if (!builder.isEmpty()) { - targetExample.getCriteria().add(builder.build()); + targetExample.getCriteria().add(builder.toCriterion()); } else { - targetExample.setAbandoned(true); + targetExampleWrapper.setAbandoned(true); } } } @@ -159,7 +155,7 @@ public class DefaultExampleBuilder implements ExampleBuilder { fieldValue = binder.output(context, fieldValue); builder.append(fieldValue); } else { - builder.clear(); + builder.clearRemainder(); break; } } @@ -168,9 +164,10 @@ public class DefaultExampleBuilder implements ExampleBuilder { @Data @AllArgsConstructor - public static class RepoExample { + public static class ExampleWrapper { private MergedRepository mergedRepository; - private BuildExample buildExample; + private Example example; + private boolean abandoned; } } diff --git a/dorive-coating/src/main/java/com/gitee/dorive/coating/impl/resolver/MergedRepositoryResolver.java b/dorive-query/src/main/java/com/gitee/dorive/query/impl/resolver/MergedRepositoryResolver.java similarity index 97% rename from dorive-coating/src/main/java/com/gitee/dorive/coating/impl/resolver/MergedRepositoryResolver.java rename to dorive-query/src/main/java/com/gitee/dorive/query/impl/resolver/MergedRepositoryResolver.java index cc1a22872963489a3a5342ab38abfc91239a9e6f..bcbef8da4778c38bf012af5e3fce713daf0d8d7e 100644 --- a/dorive-coating/src/main/java/com/gitee/dorive/coating/impl/resolver/MergedRepositoryResolver.java +++ b/dorive-query/src/main/java/com/gitee/dorive/query/impl/resolver/MergedRepositoryResolver.java @@ -15,10 +15,10 @@ * limitations under the License. */ -package com.gitee.dorive.coating.impl.resolver; +package com.gitee.dorive.query.impl.resolver; import cn.hutool.core.util.StrUtil; -import com.gitee.dorive.coating.entity.MergedRepository; +import com.gitee.dorive.query.entity.MergedRepository; import com.gitee.dorive.core.impl.binder.PropertyBinder; import com.gitee.dorive.core.impl.resolver.BinderResolver; import com.gitee.dorive.core.repository.AbstractContextRepository; @@ -73,10 +73,10 @@ public class MergedRepositoryResolver { MergedRepository mergedRepository = new MergedRepository( lastAccessPath, absoluteAccessPath, + relativeAccessPath, + abstractContextRepository != null, repository, getMergedBindersMap(lastAccessPath, repository), - abstractContextRepository != null, - relativeAccessPath, executedRepository, mergedRepositoryMap.size() + 1); addMergedRepository(mergedRepository); diff --git a/dorive-coating/src/main/java/com/gitee/dorive/coating/entity/CoatingType.java b/dorive-query/src/main/java/com/gitee/dorive/query/impl/resolver/QueryResolver.java similarity index 42% rename from dorive-coating/src/main/java/com/gitee/dorive/coating/entity/CoatingType.java rename to dorive-query/src/main/java/com/gitee/dorive/query/impl/resolver/QueryResolver.java index eea73b5bafeb36c3b00ff2879b24ab38370c0c12..0db4b7db337c01c8c6b7b2b962422a12d82a567d 100644 --- a/dorive-coating/src/main/java/com/gitee/dorive/coating/entity/CoatingType.java +++ b/dorive-query/src/main/java/com/gitee/dorive/query/impl/resolver/QueryResolver.java @@ -15,52 +15,65 @@ * limitations under the License. */ -package com.gitee.dorive.coating.entity; +package com.gitee.dorive.query.impl.resolver; -import com.gitee.dorive.coating.entity.def.ExampleDef; -import com.gitee.dorive.coating.entity.def.CriterionDef; +import com.gitee.dorive.api.constant.Operator; import com.gitee.dorive.core.entity.executor.Criterion; -import com.gitee.dorive.core.entity.executor.OrderBy; -import com.gitee.dorive.core.entity.executor.Page; +import com.gitee.dorive.core.entity.executor.Example; +import com.gitee.dorive.core.entity.executor.InnerExample; +import com.gitee.dorive.query.constant.OperatorV2; +import com.gitee.dorive.query.entity.MergedRepository; +import com.gitee.dorive.query.entity.QueryContext; +import com.gitee.dorive.query.entity.QueryField; +import com.gitee.dorive.query.entity.QueryWrapper; +import com.gitee.dorive.query.entity.SpecificFields; +import com.gitee.dorive.query.entity.def.CriterionDef; +import com.gitee.dorive.query.entity.def.ExampleDef; import lombok.AllArgsConstructor; import lombok.Data; -import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @Data @AllArgsConstructor -public class CoatingType { +public class QueryResolver { private ExampleDef exampleDef; - private List coatingFields; + private List queryFields; private SpecificFields specificFields; private List mergedRepositories; private List reversedMergedRepositories; - public CoatingCriteria newCriteria(Object coating) { - Map> criteriaMap = newCriteriaMap(coating); - OrderBy orderBy = specificFields.newOrderBy(coating); - Page page = specificFields.newPage(coating); - return new CoatingCriteria(criteriaMap, orderBy, page); + public void resolve(QueryContext queryContext, QueryWrapper queryWrapper) { + Object query = queryWrapper.getQuery(); + Map exampleMap = newExampleMap(query); + Example example = exampleMap.computeIfAbsent("/", key -> new InnerExample()); + example.setOrderBy(specificFields.newOrderBy(query)); + example.setPage(specificFields.newPage(query)); + queryContext.setExampleMap(exampleMap); + queryContext.setExample(example); } - public Map> newCriteriaMap(Object coating) { - Map> criteriaMap = new LinkedHashMap<>(8); - for (CoatingField coatingField : coatingFields) { - Object fieldValue = coatingField.getFieldValue(coating); + private Map newExampleMap(Object query) { + Map exampleMap = new LinkedHashMap<>(8); + for (QueryField queryField : queryFields) { + Object fieldValue = queryField.getFieldValue(query); if (fieldValue != null) { - CriterionDef criterionDef = coatingField.getCriterionDef(); + CriterionDef criterionDef = queryField.getCriterionDef(); String belongTo = criterionDef.getBelongTo(); String fieldName = criterionDef.getField(); String operator = criterionDef.getOperator(); - List criteria = criteriaMap.computeIfAbsent(belongTo, key -> new ArrayList<>(4)); - criteria.add(new Criterion(fieldName, operator, fieldValue)); + if (OperatorV2.NULL_SWITCH.equals(operator) && fieldValue instanceof Boolean) { + operator = (Boolean) fieldValue ? Operator.IS_NULL : Operator.IS_NOT_NULL; + fieldValue = null; + } + Example example = exampleMap.computeIfAbsent(belongTo, key -> new InnerExample()); + example.getCriteria().add(new Criterion(fieldName, operator, fieldValue)); } } - return criteriaMap; + return exampleMap; } } diff --git a/dorive-coating/src/main/java/com/gitee/dorive/coating/impl/resolver/CoatingTypeResolver.java b/dorive-query/src/main/java/com/gitee/dorive/query/impl/resolver/QueryTypeResolver.java similarity index 62% rename from dorive-coating/src/main/java/com/gitee/dorive/coating/impl/resolver/CoatingTypeResolver.java rename to dorive-query/src/main/java/com/gitee/dorive/query/impl/resolver/QueryTypeResolver.java index 998cd5c17f89bd4c095fabd2ab634b59bed6bd0a..f2e22a199cfdf18c33dd3d751a31cd111ce0d693 100644 --- a/dorive-coating/src/main/java/com/gitee/dorive/coating/impl/resolver/CoatingTypeResolver.java +++ b/dorive-query/src/main/java/com/gitee/dorive/query/impl/resolver/QueryTypeResolver.java @@ -15,18 +15,17 @@ * limitations under the License. */ -package com.gitee.dorive.coating.impl.resolver; +package com.gitee.dorive.query.impl.resolver; import cn.hutool.core.lang.Assert; -import com.gitee.dorive.coating.entity.CoatingField; -import com.gitee.dorive.coating.entity.CoatingType; -import com.gitee.dorive.coating.entity.MergedRepository; -import com.gitee.dorive.coating.entity.SpecificFields; -import com.gitee.dorive.coating.entity.def.CoatingScanDef; -import com.gitee.dorive.coating.entity.def.CriterionDef; -import com.gitee.dorive.coating.entity.def.ExampleDef; -import com.gitee.dorive.coating.repository.AbstractCoatingRepository; -import com.gitee.dorive.coating.util.ResourceUtils; +import com.gitee.dorive.query.entity.QueryField; +import com.gitee.dorive.query.entity.MergedRepository; +import com.gitee.dorive.query.entity.SpecificFields; +import com.gitee.dorive.query.entity.def.QueryScanDef; +import com.gitee.dorive.query.entity.def.CriterionDef; +import com.gitee.dorive.query.entity.def.ExampleDef; +import com.gitee.dorive.query.repository.AbstractQueryRepository; +import com.gitee.dorive.query.util.ResourceUtils; import com.gitee.dorive.core.repository.CommonRepository; import lombok.Data; import org.springframework.util.ReflectionUtils; @@ -42,24 +41,24 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.regex.Pattern; @Data -public class CoatingTypeResolver { +public class QueryTypeResolver { private static Map>> scannedClasses = new ConcurrentHashMap<>(); - private AbstractCoatingRepository repository; - private Map, CoatingType> classCoatingTypeMap = new ConcurrentHashMap<>(); - private Map nameCoatingTypeMap = new ConcurrentHashMap<>(); + private AbstractQueryRepository repository; + private Map, QueryResolver> classQueryResolverMap = new ConcurrentHashMap<>(); + private Map nameQueryResolverMap = new ConcurrentHashMap<>(); - public CoatingTypeResolver(AbstractCoatingRepository repository) throws Exception { + public QueryTypeResolver(AbstractQueryRepository repository) throws Exception { this.repository = repository; resolve(); } public void resolve() throws Exception { - CoatingScanDef coatingScanDef = repository.getCoatingScanDef(); - String[] scanPackages = coatingScanDef.getValue(); - String regex = coatingScanDef.getRegex(); - Class[] queries = coatingScanDef.getQueries(); + QueryScanDef queryScanDef = repository.getQueryScanDef(); + String[] scanPackages = queryScanDef.getValue(); + String regex = queryScanDef.getRegex(); + Class[] queries = queryScanDef.getQueries(); Pattern pattern = Pattern.compile(regex); for (String scanPackage : scanPackages) { @@ -68,56 +67,56 @@ public class CoatingTypeResolver { classes = ResourceUtils.resolveClasses(scanPackage); scannedClasses.put(scanPackage, classes); } - for (Class coatingClass : classes) { - String simpleName = coatingClass.getSimpleName(); + for (Class queryClass : classes) { + String simpleName = queryClass.getSimpleName(); if (pattern.matcher(simpleName).matches()) { - resolveCoatingClass(coatingClass); + resolveQueryClass(queryClass); } } } - for (Class coatingClass : queries) { - resolveCoatingClass(coatingClass); + for (Class queryClass : queries) { + resolveQueryClass(queryClass); } } - private void resolveCoatingClass(Class coatingClass) { - ExampleDef exampleDef = ExampleDef.fromElement(coatingClass); + private void resolveQueryClass(Class queryClass) { + ExampleDef exampleDef = ExampleDef.fromElement(queryClass); if (exampleDef == null) { return; } - List coatingFields = new ArrayList<>(); + List queryFields = new ArrayList<>(); SpecificFields specificFields = new SpecificFields(); - ReflectionUtils.doWithLocalFields(coatingClass, declaredField -> { - CoatingField coatingField = new CoatingField(declaredField); - if (coatingField.isIgnore()) { + ReflectionUtils.doWithLocalFields(queryClass, declaredField -> { + QueryField queryField = new QueryField(declaredField); + if (queryField.isIgnore()) { return; } - if (!specificFields.tryAddField(coatingField)) { - coatingFields.add(coatingField); + if (!specificFields.tryAddField(queryField)) { + queryFields.add(queryField); } }); - List mergedRepositories = matchMergedRepositories(coatingFields); + List mergedRepositories = matchMergedRepositories(queryFields); List reversedMergedRepositories = new ArrayList<>(mergedRepositories); Collections.reverse(reversedMergedRepositories); - CoatingType coatingType = new CoatingType(exampleDef, coatingFields, specificFields, mergedRepositories, reversedMergedRepositories); - classCoatingTypeMap.put(coatingClass, coatingType); - nameCoatingTypeMap.put(coatingClass.getName(), coatingType); + QueryResolver queryResolver = new QueryResolver(exampleDef, queryFields, specificFields, mergedRepositories, reversedMergedRepositories); + classQueryResolverMap.put(queryClass, queryResolver); + nameQueryResolverMap.put(queryClass.getName(), queryResolver); } - private List matchMergedRepositories(List coatingFields) { + private List matchMergedRepositories(List queryFields) { MergedRepositoryResolver mergedRepositoryResolver = repository.getMergedRepositoryResolver(); Map mergedRepositoryMap = mergedRepositoryResolver.getMergedRepositoryMap(); Map nameMergedRepositoryMap = mergedRepositoryResolver.getNameMergedRepositoryMap(); Set mergedRepositorySet = new LinkedHashSet<>(); - for (CoatingField coatingField : coatingFields) { - CriterionDef criterionDef = coatingField.getCriterionDef(); + for (QueryField queryField : queryFields) { + CriterionDef criterionDef = queryField.getCriterionDef(); String belongTo = criterionDef.getBelongTo(); String field = criterionDef.getField(); @@ -132,8 +131,8 @@ public class CoatingTypeResolver { CommonRepository repository = mergedRepository.getExecutedRepository(); Assert.isTrue(repository.hasField(field), - "The field of @Criterion does not exist in the entity! coating field: {}, entity: {}, field: {}", - coatingField.getField(), repository.getEntityEle().getElement(), field); + "The field of @Criterion does not exist in the entity! query field: {}, entity: {}, field: {}", + queryField.getField(), repository.getEntityEle().getElement(), field); mergedRepositorySet.add(mergedRepository); } diff --git a/dorive-coating/src/main/java/com/gitee/dorive/coating/repository/AbstractCoatingRepository.java b/dorive-query/src/main/java/com/gitee/dorive/query/repository/AbstractQueryRepository.java similarity index 31% rename from dorive-coating/src/main/java/com/gitee/dorive/coating/repository/AbstractCoatingRepository.java rename to dorive-query/src/main/java/com/gitee/dorive/query/repository/AbstractQueryRepository.java index 3581899615d1e96837b88c6fa700e0bb00f16b64..ad943bed02b479d8940e96d0726cda4235e9ef23 100644 --- a/dorive-coating/src/main/java/com/gitee/dorive/coating/repository/AbstractCoatingRepository.java +++ b/dorive-query/src/main/java/com/gitee/dorive/query/repository/AbstractQueryRepository.java @@ -15,93 +15,107 @@ * limitations under the License. */ -package com.gitee.dorive.coating.repository; +package com.gitee.dorive.query.repository; import cn.hutool.core.lang.Assert; import com.gitee.dorive.api.annotation.Repository; -import com.gitee.dorive.coating.api.CoatingRepository; -import com.gitee.dorive.coating.api.ExampleBuilder; -import com.gitee.dorive.coating.entity.BuildExample; -import com.gitee.dorive.coating.entity.CoatingType; -import com.gitee.dorive.coating.entity.def.CoatingScanDef; -import com.gitee.dorive.coating.impl.DefaultExampleBuilder; -import com.gitee.dorive.coating.impl.resolver.CoatingTypeResolver; -import com.gitee.dorive.coating.impl.resolver.MergedRepositoryResolver; import com.gitee.dorive.core.api.context.Context; +import com.gitee.dorive.core.api.context.Options; import com.gitee.dorive.core.entity.executor.Page; +import com.gitee.dorive.core.entity.executor.Result; import com.gitee.dorive.event.repository.AbstractEventRepository; +import com.gitee.dorive.query.api.QueryExecutor; +import com.gitee.dorive.query.api.QueryRepository; +import com.gitee.dorive.query.entity.QueryContext; +import com.gitee.dorive.query.entity.QueryWrapper; +import com.gitee.dorive.query.entity.def.QueryScanDef; +import com.gitee.dorive.query.entity.enums.ResultType; +import com.gitee.dorive.query.impl.executor.SimpleQueryExecutor; +import com.gitee.dorive.query.impl.executor.StepwiseQueryExecutor; +import com.gitee.dorive.query.impl.resolver.MergedRepositoryResolver; +import com.gitee.dorive.query.impl.resolver.QueryResolver; +import com.gitee.dorive.query.impl.resolver.QueryTypeResolver; import lombok.Data; import lombok.EqualsAndHashCode; import org.apache.commons.lang3.StringUtils; import org.springframework.core.annotation.AnnotatedElementUtils; -import java.util.Collections; import java.util.List; import java.util.Map; @Data @EqualsAndHashCode(callSuper = false) -public abstract class AbstractCoatingRepository extends AbstractEventRepository implements ExampleBuilder, CoatingRepository { +public abstract class AbstractQueryRepository extends AbstractEventRepository implements QueryRepository, QueryExecutor { - private CoatingScanDef coatingScanDef; + private QueryScanDef queryScanDef; private MergedRepositoryResolver mergedRepositoryResolver; - private CoatingTypeResolver coatingTypeResolver; - private ExampleBuilder exampleBuilder; + private QueryTypeResolver queryTypeResolver; + private QueryExecutor simpleQueryExecutor; + private QueryExecutor stepwiseQueryExecutor; @Override public void afterPropertiesSet() throws Exception { super.afterPropertiesSet(); Repository repository = AnnotatedElementUtils.getMergedAnnotation(this.getClass(), Repository.class); - coatingScanDef = CoatingScanDef.fromElement(this.getClass()); - if (repository != null && coatingScanDef != null) { - if (StringUtils.isBlank(coatingScanDef.getRegex())) { - coatingScanDef.setRegex("^" + getEntityClass().getSimpleName() + ".*"); + this.queryScanDef = QueryScanDef.fromElement(this.getClass()); + if (repository != null && this.queryScanDef != null) { + if (StringUtils.isBlank(this.queryScanDef.getRegex())) { + this.queryScanDef.setRegex("^" + getEntityClass().getSimpleName() + ".*"); } - mergedRepositoryResolver = new MergedRepositoryResolver(this); - coatingTypeResolver = new CoatingTypeResolver(this); - exampleBuilder = new DefaultExampleBuilder(this); + this.mergedRepositoryResolver = new MergedRepositoryResolver(this); + this.queryTypeResolver = new QueryTypeResolver(this); + this.simpleQueryExecutor = new SimpleQueryExecutor(this); + this.stepwiseQueryExecutor = new StepwiseQueryExecutor(this); } } - public CoatingType getCoatingType(Object coating) { - Map nameCoatingTypeMap = coatingTypeResolver.getNameCoatingTypeMap(); - CoatingType coatingType = nameCoatingTypeMap.get(coating.getClass().getName()); - Assert.notNull(coatingType, "No coating type found!"); - return coatingType; + @Override + @SuppressWarnings("unchecked") + public List selectByQuery(Options options, Object query) { + QueryContext queryContext = new QueryContext((Context) options, ResultType.DATA); + QueryWrapper queryWrapper = new QueryWrapper(query); + Result result = executeQuery(queryContext, queryWrapper); + return (List) result.getRecords(); } @Override - public BuildExample buildExample(Context context, Object coating) { - return exampleBuilder.buildExample(context, coating); + @SuppressWarnings("unchecked") + public Page selectPageByQuery(Options options, Object query) { + QueryContext queryContext = new QueryContext((Context) options, ResultType.COUNT_AND_DATA); + QueryWrapper queryWrapper = new QueryWrapper(query); + Result result = executeQuery(queryContext, queryWrapper); + return (Page) result.getPage(); } @Override - public List selectByCoating(Context context, Object coating) { - BuildExample buildExample = buildExample(context, coating); - if (buildExample.isAbandoned()) { - return Collections.emptyList(); - } - if (buildExample.isCountQueried()) { - buildExample.setPage(null); - } - return selectByExample(context, buildExample); + public long selectCountByQuery(Options options, Object query) { + QueryContext queryContext = new QueryContext((Context) options, ResultType.COUNT); + QueryWrapper queryWrapper = new QueryWrapper(query); + Result result = executeQuery(queryContext, queryWrapper); + return result.getCount(); } @Override - @SuppressWarnings("unchecked") - public Page selectPageByCoating(Context context, Object coating) { - BuildExample buildExample = buildExample(context, coating); - if (buildExample.isAbandoned()) { - return (Page) buildExample.getPage(); + public Result executeQuery(QueryContext queryContext, QueryWrapper queryWrapper) { + resolveQuery(queryContext, queryWrapper); + if (queryContext.isSimpleQuery()) { + return simpleQueryExecutor.executeQuery(queryContext, queryWrapper); + } else { + QueryExecutor queryExecutor = adaptiveQueryExecutor(queryContext, queryWrapper); + return queryExecutor.executeQuery(queryContext, queryWrapper); } - if (buildExample.isCountQueried()) { - Page page = buildExample.getPage(); - buildExample.setPage(null); - List records = selectByExample(context, buildExample); - page.setRecords((List) records); - return (Page) page; - } - return selectPageByExample(context, buildExample); + } + + public void resolveQuery(QueryContext queryContext, QueryWrapper queryWrapper) { + Map nameQueryResolverMap = queryTypeResolver.getNameQueryResolverMap(); + QueryResolver queryResolver = nameQueryResolverMap.get(queryWrapper.getQuery().getClass().getName()); + Assert.notNull(queryResolver, "No query resolver found!"); + queryContext.setQueryResolver(queryResolver); + queryResolver.resolve(queryContext, queryWrapper); + } + + protected QueryExecutor adaptiveQueryExecutor(QueryContext queryContext, QueryWrapper queryWrapper) { + return stepwiseQueryExecutor; } } diff --git a/dorive-coating/src/main/java/com/gitee/dorive/coating/util/ResourceUtils.java b/dorive-query/src/main/java/com/gitee/dorive/query/util/ResourceUtils.java similarity index 98% rename from dorive-coating/src/main/java/com/gitee/dorive/coating/util/ResourceUtils.java rename to dorive-query/src/main/java/com/gitee/dorive/query/util/ResourceUtils.java index e9ed74cc59069f02c44d231e1590e4b95fb83372..ca473ac4653ff951b1cb38e1d8ae70bac6d3c9ba 100644 --- a/dorive-coating/src/main/java/com/gitee/dorive/coating/util/ResourceUtils.java +++ b/dorive-query/src/main/java/com/gitee/dorive/query/util/ResourceUtils.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package com.gitee.dorive.coating.util; +package com.gitee.dorive.query.util; import org.springframework.core.io.Resource; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; diff --git a/dorive-ref/pom.xml b/dorive-ref/pom.xml index 713efc5061f9ca95596364e305a5a9245d9182c6..28b8008121254f440d7467b1555c19ee7da073b5 100644 --- a/dorive-ref/pom.xml +++ b/dorive-ref/pom.xml @@ -6,13 +6,13 @@ com.gitee.digital-engine dorive - 3.4.3.1 + 3.4.3.3 dorive-ref com.gitee.digital-engine - dorive-coating + dorive-query ${project.version} diff --git a/dorive-ref/src/main/java/com/gitee/dorive/ref/api/Ref.java b/dorive-ref/src/main/java/com/gitee/dorive/ref/api/Ref.java index 44d96d8cfedf4bcf1063a3081a1c78ae714646b7..746fc2a275fb988b8d84a227722d331ef013e93e 100644 --- a/dorive-ref/src/main/java/com/gitee/dorive/ref/api/Ref.java +++ b/dorive-ref/src/main/java/com/gitee/dorive/ref/api/Ref.java @@ -17,9 +17,10 @@ package com.gitee.dorive.ref.api; +import com.gitee.dorive.query.api.QueryRepository; import com.gitee.dorive.ref.repository.AbstractRefRepository; -public interface Ref extends SelectorRepository { +public interface Ref extends QueryRepository { > R get(); diff --git a/dorive-ref/src/main/java/com/gitee/dorive/ref/api/RefObj.java b/dorive-ref/src/main/java/com/gitee/dorive/ref/api/RefObj.java index 4c28909cd4850317bb859ebb23d3f73ba1f6ece2..1bc88782fb341fdcf8cf61a95cf316c7630fbff8 100644 --- a/dorive-ref/src/main/java/com/gitee/dorive/ref/api/RefObj.java +++ b/dorive-ref/src/main/java/com/gitee/dorive/ref/api/RefObj.java @@ -17,21 +17,14 @@ package com.gitee.dorive.ref.api; -import com.gitee.dorive.core.api.context.Context; -import com.gitee.dorive.core.api.context.Selector; +import com.gitee.dorive.core.api.context.Options; public interface RefObj { - long select(Context context); + long select(Options options); - int insertOrUpdate(Context context); + int insertOrUpdate(Options options); - int delete(Context context); - - long select(Selector selector); - - int insertOrUpdate(Selector selector); - - int delete(Selector selector); + int delete(Options options); } diff --git a/dorive-ref/src/main/java/com/gitee/dorive/ref/api/SelectorRepository.java b/dorive-ref/src/main/java/com/gitee/dorive/ref/api/SelectorRepository.java deleted file mode 100644 index c2eba9d50853af34b40185adc7d73a204453be3f..0000000000000000000000000000000000000000 --- a/dorive-ref/src/main/java/com/gitee/dorive/ref/api/SelectorRepository.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.gitee.dorive.ref.api; - -import com.gitee.dorive.coating.api.CoatingRepository; -import com.gitee.dorive.core.api.context.Selector; -import com.gitee.dorive.core.entity.context.InnerContext; -import com.gitee.dorive.core.entity.executor.Example; -import com.gitee.dorive.core.entity.executor.Page; - -import java.util.List; - -public interface SelectorRepository extends CoatingRepository { - - default E selectByPrimaryKey(Selector selector, PK primaryKey) { - return selectByPrimaryKey(new InnerContext(selector), primaryKey); - } - - default List selectByExample(Selector selector, Example example) { - return selectByExample(new InnerContext(selector), example); - } - - default Page selectPageByExample(Selector selector, Example example) { - return selectPageByExample(new InnerContext(selector), example); - } - - default long selectCount(Selector selector, Example example) { - return selectCount(new InnerContext(selector), example); - } - - default int insert(Selector selector, E entity) { - return insert(new InnerContext(selector), entity); - } - - default int update(Selector selector, E entity) { - return update(new InnerContext(selector), entity); - } - - default int updateByExample(Selector selector, Object entity, Example example) { - return updateByExample(new InnerContext(selector), entity, example); - } - - default int insertOrUpdate(Selector selector, E entity) { - return insertOrUpdate(new InnerContext(selector), entity); - } - - default int delete(Selector selector, E entity) { - return delete(new InnerContext(selector), entity); - } - - default int deleteByPrimaryKey(Selector selector, PK primaryKey) { - return deleteByPrimaryKey(new InnerContext(selector), primaryKey); - } - - default int deleteByExample(Selector selector, Example example) { - return deleteByExample(new InnerContext(selector), example); - } - - default int insertList(Selector selector, List entities) { - return insertList(new InnerContext(selector), entities); - } - - default int updateList(Selector selector, List entities) { - return updateList(new InnerContext(selector), entities); - } - - default int insertOrUpdateList(Selector selector, List entities) { - return insertOrUpdateList(new InnerContext(selector), entities); - } - - default int deleteList(Selector selector, List entities) { - return deleteList(new InnerContext(selector), entities); - } - - default List selectByCoating(Selector selector, Object coating) { - return selectByCoating(new InnerContext(selector), coating); - } - - default Page selectPageByCoating(Selector selector, Object coating) { - return selectPageByCoating(new InnerContext(selector), coating); - } - -} diff --git a/dorive-ref/src/main/java/com/gitee/dorive/ref/impl/RefImpl.java b/dorive-ref/src/main/java/com/gitee/dorive/ref/impl/RefImpl.java index d89e2964778bb58aa9ba5621d7ee85efba3fa5f2..4decd685f4f63df35952f3fd993c30b0c5e06580 100644 --- a/dorive-ref/src/main/java/com/gitee/dorive/ref/impl/RefImpl.java +++ b/dorive-ref/src/main/java/com/gitee/dorive/ref/impl/RefImpl.java @@ -17,7 +17,7 @@ package com.gitee.dorive.ref.impl; -import com.gitee.dorive.core.api.context.Context; +import com.gitee.dorive.core.api.context.Options; import com.gitee.dorive.core.api.executor.EntityHandler; import com.gitee.dorive.core.entity.executor.Page; import com.gitee.dorive.core.repository.AbstractProxyRepository; @@ -43,33 +43,38 @@ public class RefImpl extends AbstractProxyRepository implements Ref { } @Override - public int insertList(Context context, List entities) { - return repository.insertList(context, entities); + public int insertList(Options options, List entities) { + return repository.insertList(options, entities); } @Override - public int updateList(Context context, List entities) { - return repository.updateList(context, entities); + public int updateList(Options options, List entities) { + return repository.updateList(options, entities); } @Override - public int insertOrUpdateList(Context context, List entities) { - return repository.insertOrUpdateList(context, entities); + public int insertOrUpdateList(Options options, List entities) { + return repository.insertOrUpdateList(options, entities); } @Override - public int deleteList(Context context, List entities) { - return repository.deleteList(context, entities); + public int deleteList(Options options, List entities) { + return repository.deleteList(options, entities); } @Override - public List selectByCoating(Context context, Object coating) { - return repository.selectByCoating(context, coating); + public List selectByQuery(Options options, Object query) { + return repository.selectByQuery(options, query); } @Override - public Page selectPageByCoating(Context context, Object coating) { - return repository.selectPageByCoating(context, coating); + public Page selectPageByQuery(Options options, Object query) { + return repository.selectPageByQuery(options, query); + } + + @Override + public long selectCountByQuery(Options options, Object query) { + return repository.selectCountByQuery(options, query); } @Override diff --git a/dorive-ref/src/main/java/com/gitee/dorive/ref/impl/RefInjector.java b/dorive-ref/src/main/java/com/gitee/dorive/ref/impl/RefInjector.java index f2bc4ae05174fbda0dc7259ddfa7c3fc865100da..aedd37cd9a17b3d8ded7bbd5b4a6c84a5e566182 100644 --- a/dorive-ref/src/main/java/com/gitee/dorive/ref/impl/RefInjector.java +++ b/dorive-ref/src/main/java/com/gitee/dorive/ref/impl/RefInjector.java @@ -65,7 +65,6 @@ public class RefInjector { refImpl.setEntityEle(repository.getEntityEle()); refImpl.setOperationFactory(repository.getOperationFactory()); refImpl.setExecutor(repository.getExecutor()); - refImpl.setAttachments(repository.getAttachments()); return refImpl; } diff --git a/dorive-ref/src/main/java/com/gitee/dorive/ref/impl/RefObjImpl.java b/dorive-ref/src/main/java/com/gitee/dorive/ref/impl/RefObjImpl.java index 5fd2bead635c8e28dbddd49b057ea8f1a54c0455..4299fd72dcafdae974ce6cfd02fc3fd12838f837 100644 --- a/dorive-ref/src/main/java/com/gitee/dorive/ref/impl/RefObjImpl.java +++ b/dorive-ref/src/main/java/com/gitee/dorive/ref/impl/RefObjImpl.java @@ -18,7 +18,7 @@ package com.gitee.dorive.ref.impl; import com.gitee.dorive.core.api.context.Context; -import com.gitee.dorive.core.api.context.Selector; +import com.gitee.dorive.core.api.context.Options; import com.gitee.dorive.core.api.executor.EntityHandler; import com.gitee.dorive.core.entity.context.InnerContext; import com.gitee.dorive.core.repository.AbstractRepository; @@ -36,36 +36,30 @@ public class RefObjImpl implements RefObj { private Object object; @Override - public long select(Context context) { + public long select(Options options) { + if (!(options instanceof Context)) { + options = new InnerContext(options); + } EntityHandler entityHandler = ref.getEntityHandler(); - return entityHandler.handle(context, Collections.singletonList(object)); + return entityHandler.handle((Context) options, Collections.singletonList(object)); } @Override - public int insertOrUpdate(Context context) { + public int insertOrUpdate(Options options) { + if (!(options instanceof Context)) { + options = new InnerContext(options); + } AbstractRepository repository = ref.getProxyRepository(); - return repository.insertOrUpdate(context, object); + return repository.insertOrUpdate(options, object); } @Override - public int delete(Context context) { + public int delete(Options options) { + if (!(options instanceof Context)) { + options = new InnerContext(options); + } AbstractRepository repository = ref.getProxyRepository(); - return repository.delete(context, object); - } - - @Override - public long select(Selector selector) { - return select(new InnerContext(selector)); - } - - @Override - public int insertOrUpdate(Selector selector) { - return insertOrUpdate(new InnerContext(selector)); - } - - @Override - public int delete(Selector selector) { - return delete(new InnerContext(selector)); + return repository.delete(options, object); } } diff --git a/dorive-ref/src/main/java/com/gitee/dorive/ref/repository/AbstractInnerRepository.java b/dorive-ref/src/main/java/com/gitee/dorive/ref/repository/AbstractInnerRepository.java new file mode 100644 index 0000000000000000000000000000000000000000..e038cbd297af5070eb4b7e89e8b096fd756a72b2 --- /dev/null +++ b/dorive-ref/src/main/java/com/gitee/dorive/ref/repository/AbstractInnerRepository.java @@ -0,0 +1,203 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.gitee.dorive.ref.repository; + +import com.gitee.dorive.core.api.context.Context; +import com.gitee.dorive.core.api.context.Options; +import com.gitee.dorive.core.entity.context.InnerContext; +import com.gitee.dorive.core.entity.executor.Example; +import com.gitee.dorive.core.entity.executor.InnerExample; +import com.gitee.dorive.core.entity.executor.Page; +import com.gitee.dorive.core.util.ExampleUtils; +import com.gitee.dorive.query.repository.AbstractQueryRepository; + +import java.util.List; + +public abstract class AbstractInnerRepository extends AbstractQueryRepository { + + @Override + public E selectByPrimaryKey(Options options, PK primaryKey) { + if (!(options instanceof Context)) { + options = new InnerContext(options); + } + return super.selectByPrimaryKey(options, primaryKey); + } + + @Override + public List selectByExample(Options options, Example example) { + if (!(options instanceof Context)) { + options = new InnerContext(options); + } + if (!(example instanceof InnerExample)) { + example = ExampleUtils.clone(example); + } + return super.selectByExample(options, example); + } + + @Override + public E selectOneByExample(Options options, Example example) { + if (!(options instanceof Context)) { + options = new InnerContext(options); + } + if (!(example instanceof InnerExample)) { + example = ExampleUtils.clone(example); + } + return super.selectOneByExample(options, example); + } + + @Override + public Page selectPageByExample(Options options, Example example) { + if (!(options instanceof Context)) { + options = new InnerContext(options); + } + if (!(example instanceof InnerExample)) { + example = ExampleUtils.clone(example); + } + return super.selectPageByExample(options, example); + } + + @Override + public long selectCountByExample(Options options, Example example) { + if (!(options instanceof Context)) { + options = new InnerContext(options); + } + if (!(example instanceof InnerExample)) { + example = ExampleUtils.clone(example); + } + return super.selectCountByExample(options, example); + } + + @Override + public int insert(Options options, E entity) { + if (!(options instanceof Context)) { + options = new InnerContext(options); + } + return super.insert(options, entity); + } + + @Override + public int update(Options options, E entity) { + if (!(options instanceof Context)) { + options = new InnerContext(options); + } + return super.update(options, entity); + } + + @Override + public int updateByExample(Options options, Object entity, Example example) { + if (!(options instanceof Context)) { + options = new InnerContext(options); + } + if (!(example instanceof InnerExample)) { + example = ExampleUtils.clone(example); + } + return super.updateByExample(options, entity, example); + } + + @Override + public int insertOrUpdate(Options options, E entity) { + if (!(options instanceof Context)) { + options = new InnerContext(options); + } + return super.insertOrUpdate(options, entity); + } + + @Override + public int delete(Options options, E entity) { + if (!(options instanceof Context)) { + options = new InnerContext(options); + } + return super.delete(options, entity); + } + + @Override + public int deleteByPrimaryKey(Options options, PK primaryKey) { + if (!(options instanceof Context)) { + options = new InnerContext(options); + } + return super.deleteByPrimaryKey(options, primaryKey); + } + + @Override + public int deleteByExample(Options options, Example example) { + if (!(options instanceof Context)) { + options = new InnerContext(options); + } + if (!(example instanceof InnerExample)) { + example = ExampleUtils.clone(example); + } + return super.deleteByExample(options, example); + } + + @Override + public int insertList(Options options, List entities) { + if (!(options instanceof Context)) { + options = new InnerContext(options); + } + return super.insertList(options, entities); + } + + @Override + public int updateList(Options options, List entities) { + if (!(options instanceof Context)) { + options = new InnerContext(options); + } + return super.updateList(options, entities); + } + + @Override + public int insertOrUpdateList(Options options, List entities) { + if (!(options instanceof Context)) { + options = new InnerContext(options); + } + return super.insertOrUpdateList(options, entities); + } + + @Override + public int deleteList(Options options, List entities) { + if (!(options instanceof Context)) { + options = new InnerContext(options); + } + return super.deleteList(options, entities); + } + + @Override + public List selectByQuery(Options options, Object query) { + if (!(options instanceof Context)) { + options = new InnerContext(options); + } + return super.selectByQuery(options, query); + } + + @Override + public Page selectPageByQuery(Options options, Object query) { + if (!(options instanceof Context)) { + options = new InnerContext(options); + } + return super.selectPageByQuery(options, query); + } + + @Override + public long selectCountByQuery(Options options, Object query) { + if (!(options instanceof Context)) { + options = new InnerContext(options); + } + return super.selectCountByQuery(options, query); + } + +} diff --git a/dorive-ref/src/main/java/com/gitee/dorive/ref/repository/AbstractRefRepository.java b/dorive-ref/src/main/java/com/gitee/dorive/ref/repository/AbstractRefRepository.java index b97108dc2acb6d4ed6ca9d9b1c6426d66def6d6d..96baba7ed03207c1c1b890ad3331af4322f93ff2 100644 --- a/dorive-ref/src/main/java/com/gitee/dorive/ref/repository/AbstractRefRepository.java +++ b/dorive-ref/src/main/java/com/gitee/dorive/ref/repository/AbstractRefRepository.java @@ -17,12 +17,10 @@ package com.gitee.dorive.ref.repository; -import com.gitee.dorive.coating.repository.AbstractCoatingRepository; import com.gitee.dorive.core.api.executor.EntityHandler; -import com.gitee.dorive.ref.api.SelectorRepository; import com.gitee.dorive.ref.impl.RefInjector; -public abstract class AbstractRefRepository extends AbstractCoatingRepository implements SelectorRepository { +public abstract class AbstractRefRepository extends AbstractInnerRepository { @Override protected EntityHandler processEntityHandler(EntityHandler entityHandler) { diff --git a/dorive-spring-boot-starter/pom.xml b/dorive-spring-boot-starter/pom.xml index ec641d113d78f766f4e795ece67589fdd719bce9..d43c948a51414c5fd3d963f74c054ca8f0908d13 100644 --- a/dorive-spring-boot-starter/pom.xml +++ b/dorive-spring-boot-starter/pom.xml @@ -6,18 +6,13 @@ com.gitee.digital-engine dorive - 3.4.3.1 + 3.4.3.3 dorive-spring-boot-starter com.gitee.digital-engine - dorive-injection - ${project.version} - - - com.gitee.digital-engine - dorive-env + dorive-inject ${project.version} @@ -27,12 +22,8 @@ com.gitee.digital-engine - dorive-ref + dorive-mybatis-plus ${project.version} - - com.baomidou - mybatis-plus-boot-starter - \ No newline at end of file diff --git a/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/annotation/RootRepository.java b/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/annotation/RootRepository.java index 5978338fb4d321b3a4ccf4fc56c3e02b795a7ae9..2fd88bae2b165f52a37e994b75c49251a3a6f032 100644 --- a/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/annotation/RootRepository.java +++ b/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/annotation/RootRepository.java @@ -18,7 +18,7 @@ package com.gitee.dorive.spring.boot.starter.annotation; import com.gitee.dorive.api.annotation.Repository; -import com.gitee.dorive.injection.annotation.Root; +import com.gitee.dorive.inject.annotation.Root; import org.springframework.core.annotation.AliasFor; import java.lang.annotation.Documented; diff --git a/dorive-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/dorive-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports deleted file mode 100644 index 071b7b704175d88a12257bbc9350af16170efa54..0000000000000000000000000000000000000000 --- a/dorive-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ /dev/null @@ -1 +0,0 @@ -com.gitee.dorive.spring.boot.starter.config.MybatisPlusConfiguration \ No newline at end of file diff --git a/dorive-sql/pom.xml b/dorive-sql/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..bc1a34710b44c72d319d8ac0b5d25292ee5370d1 --- /dev/null +++ b/dorive-sql/pom.xml @@ -0,0 +1,19 @@ + + + 4.0.0 + + com.gitee.digital-engine + dorive + 3.4.3.3 + + dorive-sql + + + com.gitee.digital-engine + dorive-ref + ${project.version} + + + \ No newline at end of file diff --git a/dorive-sql/src/main/java/com/gitee/dorive/sql/api/SqlRunner.java b/dorive-sql/src/main/java/com/gitee/dorive/sql/api/SqlRunner.java new file mode 100644 index 0000000000000000000000000000000000000000..e825b81990bd775c11b28d4c517eba369355830e --- /dev/null +++ b/dorive-sql/src/main/java/com/gitee/dorive/sql/api/SqlRunner.java @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.gitee.dorive.sql.api; + +import java.util.List; +import java.util.Map; + +public interface SqlRunner { + + long selectCount(String sql, Object... args); + + List> selectList(String sql, Object... args); + +} diff --git a/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/entity/ArgSegment.java b/dorive-sql/src/main/java/com/gitee/dorive/sql/entity/ArgSegment.java similarity index 92% rename from dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/entity/ArgSegment.java rename to dorive-sql/src/main/java/com/gitee/dorive/sql/entity/ArgSegment.java index 5f613a35a76275b665e143974b28fce504ac0e24..c56c2079ca41c57fb841fd075733485da791872b 100644 --- a/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/entity/ArgSegment.java +++ b/dorive-sql/src/main/java/com/gitee/dorive/sql/entity/ArgSegment.java @@ -15,14 +15,12 @@ * limitations under the License. */ -package com.gitee.dorive.spring.boot.starter.entity; +package com.gitee.dorive.sql.entity; import lombok.AllArgsConstructor; import lombok.Data; -import lombok.NoArgsConstructor; @Data -@NoArgsConstructor @AllArgsConstructor public class ArgSegment { diff --git a/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/entity/JoinSegment.java b/dorive-sql/src/main/java/com/gitee/dorive/sql/entity/JoinSegment.java similarity index 79% rename from dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/entity/JoinSegment.java rename to dorive-sql/src/main/java/com/gitee/dorive/sql/entity/JoinSegment.java index 023c3bd723f517c1bc94c68e61e64674eca09f0f..f2b9fe25d4d67a9ad832a3d56f9025222dbd6906 100644 --- a/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/entity/JoinSegment.java +++ b/dorive-sql/src/main/java/com/gitee/dorive/sql/entity/JoinSegment.java @@ -15,17 +15,16 @@ * limitations under the License. */ -package com.gitee.dorive.spring.boot.starter.entity; +package com.gitee.dorive.sql.entity; +import lombok.AllArgsConstructor; import lombok.Data; -import lombok.EqualsAndHashCode; import java.util.List; @Data -@EqualsAndHashCode(callSuper = false) -public class JoinSegment extends Segment { - private String tableName; - private String tableAlias; +@AllArgsConstructor +public class JoinSegment { + private TableSegment tableSegment; private List onSegments; } diff --git a/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/entity/OnSegment.java b/dorive-sql/src/main/java/com/gitee/dorive/sql/entity/OnSegment.java similarity index 86% rename from dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/entity/OnSegment.java rename to dorive-sql/src/main/java/com/gitee/dorive/sql/entity/OnSegment.java index 53ff3a252e5d04cdac3d47c5a7e69dd4a8f4ac2a..9773da95ead6dbf8f311696f699f874b7865a2ac 100644 --- a/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/entity/OnSegment.java +++ b/dorive-sql/src/main/java/com/gitee/dorive/sql/entity/OnSegment.java @@ -15,14 +15,14 @@ * limitations under the License. */ -package com.gitee.dorive.spring.boot.starter.entity; +package com.gitee.dorive.sql.entity; +import lombok.AllArgsConstructor; import lombok.Data; -import lombok.EqualsAndHashCode; @Data -@EqualsAndHashCode(callSuper = false) -public class OnSegment extends Segment { +@AllArgsConstructor +public class OnSegment { private String tableAlias; private String column; diff --git a/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/entity/SelectSegment.java b/dorive-sql/src/main/java/com/gitee/dorive/sql/entity/SelectSegment.java similarity index 56% rename from dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/entity/SelectSegment.java rename to dorive-sql/src/main/java/com/gitee/dorive/sql/entity/SelectSegment.java index 695847cf6296d9937bf77ea4cb6cda48ade46703..f01c1393bd5e4bd47a90b3fce51e05f327cbfe88 100644 --- a/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/entity/SelectSegment.java +++ b/dorive-sql/src/main/java/com/gitee/dorive/sql/entity/SelectSegment.java @@ -15,47 +15,64 @@ * limitations under the License. */ -package com.gitee.dorive.spring.boot.starter.entity; +package com.gitee.dorive.sql.entity; import cn.hutool.core.util.StrUtil; import cn.hutool.db.sql.SqlBuilder; import lombok.Data; -import lombok.EqualsAndHashCode; +import java.util.ArrayList; +import java.util.Collections; import java.util.List; -import java.util.stream.Collectors; @Data -@EqualsAndHashCode(callSuper = false) -public class SelectSegment extends Segment { +public class SelectSegment { + private char letter = 'a'; private boolean distinct; - private List columns; - private String tableName; - private String tableAlias; - private List joinSegments; - private List argSegments; + private List selectColumns = Collections.emptyList(); + private TableSegment tableSegment; + private List joinSegments = new ArrayList<>(); + private List argSegments = new ArrayList<>(); + private List args = new ArrayList<>(); private String groupBy; private String orderBy; private String limit; + public String generateTableAlias() { + String tableAlias = String.valueOf(letter); + letter = (char) (letter + 1); + return tableAlias; + } + + public void filterTableSegments() { + if (tableSegment.isJoin()) { + argSegments.addAll(tableSegment.getArgSegments()); + } + List newJoinSegments = new ArrayList<>(joinSegments.size()); + for (JoinSegment joinSegment : joinSegments) { + TableSegment tableSegment = joinSegment.getTableSegment(); + if (tableSegment.isJoin()) { + newJoinSegments.add(joinSegment); + argSegments.addAll(tableSegment.getArgSegments()); + } + } + joinSegments = newJoinSegments; + } + public String selectSql() { SqlBuilder sqlBuilder = SqlBuilder.create(); - sqlBuilder.select(distinct, columns); + sqlBuilder.select(distinct, selectColumns); return sqlBuilder.toString(); } public String fromWhereSql() { SqlBuilder sqlBuilder = SqlBuilder.create(); - sqlBuilder.from(tableName + " " + tableAlias); + sqlBuilder.from(tableSegment.toString()); for (JoinSegment joinSegment : joinSegments) { - if (joinSegment.isAvailable()) { - sqlBuilder.join(joinSegment.getTableName() + " " + joinSegment.getTableAlias(), SqlBuilder.Join.LEFT); - List onSegments = joinSegment.getOnSegments().stream() - .filter(onSegment -> onSegment.getDirectedSegments().get(0).isAvailable()) - .collect(Collectors.toList()); - sqlBuilder.on(StrUtil.join(" AND ", onSegments)); - } + TableSegment tableSegment = joinSegment.getTableSegment(); + sqlBuilder.join(tableSegment.toString(), SqlBuilder.Join.LEFT); + sqlBuilder.on(StrUtil.join(" AND ", joinSegment.getOnSegments())); } sqlBuilder.where(StrUtil.join(" AND ", argSegments)); return sqlBuilder.toString(); diff --git a/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/entity/SegmentResult.java b/dorive-sql/src/main/java/com/gitee/dorive/sql/entity/TableSegment.java similarity index 72% rename from dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/entity/SegmentResult.java rename to dorive-sql/src/main/java/com/gitee/dorive/sql/entity/TableSegment.java index 231e3da72981d61c58c85fd720a4d00f2fd6dabe..5d563ff78174bc8dca9725f49dc9d2ef2c67e243 100644 --- a/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/entity/SegmentResult.java +++ b/dorive-sql/src/main/java/com/gitee/dorive/sql/entity/TableSegment.java @@ -15,10 +15,8 @@ * limitations under the License. */ -package com.gitee.dorive.spring.boot.starter.entity; +package com.gitee.dorive.sql.entity; -import com.gitee.dorive.core.entity.executor.OrderBy; -import com.gitee.dorive.core.entity.executor.Page; import lombok.AllArgsConstructor; import lombok.Data; @@ -26,10 +24,16 @@ import java.util.List; @Data @AllArgsConstructor -public class SegmentResult { - private char letter; - private SelectSegment selectSegment; - private List args; - private OrderBy orderBy; - private Page page; +public class TableSegment { + + private String tableName; + private String tableAlias; + private boolean join; + private List argSegments; + + @Override + public String toString() { + return tableName + " " + tableAlias; + } + } diff --git a/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/impl/CountQuerier.java b/dorive-sql/src/main/java/com/gitee/dorive/sql/impl/CountQuerier.java similarity index 40% rename from dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/impl/CountQuerier.java rename to dorive-sql/src/main/java/com/gitee/dorive/sql/impl/CountQuerier.java index 31097b70d5ea36b2f32f1f28474a098107494f9b..39bbd8f4b6781e833e0ff316e402572740bdce21 100644 --- a/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/impl/CountQuerier.java +++ b/dorive-sql/src/main/java/com/gitee/dorive/sql/impl/CountQuerier.java @@ -15,16 +15,21 @@ * limitations under the License. */ -package com.gitee.dorive.spring.boot.starter.impl; +package com.gitee.dorive.sql.impl; -import com.baomidou.mybatisplus.extension.toolkit.SqlRunner; import com.gitee.dorive.api.entity.element.EntityEle; -import com.gitee.dorive.coating.repository.AbstractCoatingRepository; import com.gitee.dorive.core.api.context.Context; -import com.gitee.dorive.core.entity.context.BoundedContext; -import com.gitee.dorive.spring.boot.starter.entity.SegmentResult; -import com.gitee.dorive.spring.boot.starter.entity.SelectSegment; +import com.gitee.dorive.query.entity.QueryContext; +import com.gitee.dorive.query.entity.enums.ResultType; +import com.gitee.dorive.query.entity.QueryWrapper; +import com.gitee.dorive.query.repository.AbstractQueryRepository; +import com.gitee.dorive.sql.api.SqlRunner; +import com.gitee.dorive.sql.entity.SelectSegment; +import com.gitee.dorive.sql.entity.TableSegment; +import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Data; +import lombok.NoArgsConstructor; import java.util.ArrayList; import java.util.LinkedHashMap; @@ -32,51 +37,52 @@ import java.util.List; import java.util.Map; @Data +@AllArgsConstructor public class CountQuerier { - private final AbstractCoatingRepository repository; - private final SegmentBuilder segmentBuilder; + private AbstractQueryRepository repository; + private SegmentBuilder segmentBuilder; + private SqlRunner sqlRunner; - public CountQuerier(AbstractCoatingRepository repository) { - this.repository = repository; - this.segmentBuilder = new SegmentBuilder(repository); - } + public Map selectCountMap(Context context, CountQuery countQuery) { + QueryContext queryContext = new QueryContext(context, ResultType.COUNT); + QueryWrapper queryWrapper = new QueryWrapper(countQuery.getQuery()); + repository.resolveQuery(queryContext, queryWrapper); - public Map selectCount(Context context, String groupField, boolean distinct, String countField, Object coating) { - SegmentResult segmentResult = segmentBuilder.buildSegment(context, coating); - SelectSegment selectSegment = segmentResult.getSelectSegment(); - List args = segmentResult.getArgs(); + SelectSegment selectSegment = segmentBuilder.buildSegment(queryContext); + TableSegment tableSegment = selectSegment.getTableSegment(); + List args = selectSegment.getArgs(); + String tableAlias = tableSegment.getTableAlias(); EntityEle entityEle = repository.getEntityEle(); - String groupByColumn = entityEle.toAlias(groupField); - String countColumn = entityEle.toAlias(countField); - - String tableAlias = selectSegment.getTableAlias(); - groupByColumn = tableAlias + "." + groupByColumn; - countColumn = tableAlias + "." + countColumn; + String countByColumn = tableAlias + "." + entityEle.toAlias(countQuery.getCountBy()); + String groupByColumn = tableAlias + "." + entityEle.toAlias(countQuery.getGroupBy()); List columns = new ArrayList<>(2); - columns.add(groupByColumn + " AS recordId"); - if (distinct) { - columns.add("count(DISTINCT " + countColumn + ") AS totalCount"); - } else { - columns.add("count(" + countColumn + ") AS totalCount"); - } - selectSegment.setColumns(columns); + columns.add(groupByColumn + " AS groupId"); + + String format = "COUNT(%s) AS total"; + String countByColumnStr = String.format(format, countQuery.isDistinct() ? "DISTINCT " + countByColumn : countByColumn); + columns.add(countByColumnStr); + + selectSegment.setSelectColumns(columns); selectSegment.setGroupBy("GROUP BY " + groupByColumn); - List> resultMaps = SqlRunner.db().selectList(selectSegment.toString(), args.toArray()); + List> resultMaps = sqlRunner.selectList(selectSegment.toString(), args.toArray()); Map countMap = new LinkedHashMap<>(resultMaps.size() * 4 / 3 + 1); - resultMaps.forEach(resultMap -> countMap.put(resultMap.get("recordId").toString(), (Long) resultMap.get("totalCount"))); + resultMaps.forEach(resultMap -> countMap.put(resultMap.get("groupId").toString(), (Long) resultMap.get("total"))); return countMap; } - public Map selectCount(Context context, String groupField, String countField, Object coating) { - return selectCount(context, groupField, true, countField, coating); - } - - public Map selectCount(String groupField, String countField, Object coating) { - return selectCount(new BoundedContext(), groupField, true, countField, coating); + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class CountQuery { + private Object query; + private boolean distinct = true; + private String countBy; + private String groupBy; } } diff --git a/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/impl/SegmentBuilder.java b/dorive-sql/src/main/java/com/gitee/dorive/sql/impl/SegmentBuilder.java similarity index 30% rename from dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/impl/SegmentBuilder.java rename to dorive-sql/src/main/java/com/gitee/dorive/sql/impl/SegmentBuilder.java index a76da67bf433593ea2106da6d09a951b1807c159..e34673e084cfcf4e20882246be70b8b8ab2a6d19 100644 --- a/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/impl/SegmentBuilder.java +++ b/dorive-sql/src/main/java/com/gitee/dorive/sql/impl/SegmentBuilder.java @@ -15,127 +15,112 @@ * limitations under the License. */ -package com.gitee.dorive.spring.boot.starter.impl; +package com.gitee.dorive.sql.impl; -import com.baomidou.mybatisplus.core.metadata.TableInfo; import com.gitee.dorive.api.constant.Operator; -import com.gitee.dorive.coating.entity.CoatingCriteria; -import com.gitee.dorive.coating.entity.CoatingType; -import com.gitee.dorive.coating.entity.MergedRepository; -import com.gitee.dorive.coating.repository.AbstractCoatingRepository; +import com.gitee.dorive.api.entity.element.EntityEle; import com.gitee.dorive.core.api.context.Context; +import com.gitee.dorive.core.entity.common.EntityStoreInfo; import com.gitee.dorive.core.entity.executor.Criterion; -import com.gitee.dorive.core.entity.executor.OrderBy; -import com.gitee.dorive.core.entity.executor.Page; +import com.gitee.dorive.core.entity.executor.Example; +import com.gitee.dorive.core.entity.executor.InnerExample; import com.gitee.dorive.core.impl.binder.PropertyBinder; +import com.gitee.dorive.core.impl.executor.ExampleExecutor; import com.gitee.dorive.core.impl.resolver.BinderResolver; +import com.gitee.dorive.core.repository.AbstractContextRepository; import com.gitee.dorive.core.repository.CommonRepository; -import com.gitee.dorive.api.constant.Keys; -import com.gitee.dorive.spring.boot.starter.entity.ArgSegment; -import com.gitee.dorive.spring.boot.starter.entity.JoinSegment; -import com.gitee.dorive.spring.boot.starter.entity.OnSegment; -import com.gitee.dorive.spring.boot.starter.entity.Segment; -import com.gitee.dorive.spring.boot.starter.entity.SegmentResult; -import com.gitee.dorive.spring.boot.starter.entity.SelectSegment; -import com.gitee.dorive.core.impl.executor.FieldExecutor; -import com.gitee.dorive.spring.boot.starter.util.CriterionUtils; +import com.gitee.dorive.core.util.CriterionUtils; +import com.gitee.dorive.query.entity.MergedRepository; +import com.gitee.dorive.query.entity.QueryContext; +import com.gitee.dorive.query.impl.resolver.QueryResolver; +import com.gitee.dorive.sql.entity.*; import lombok.AllArgsConstructor; import lombok.Data; -import java.util.ArrayList; -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; +import java.util.*; @Data -@AllArgsConstructor public class SegmentBuilder { - private final AbstractCoatingRepository repository; + public SelectSegment buildSegment(QueryContext queryContext) { + Context context = queryContext.getContext(); + QueryResolver queryResolver = queryContext.getQueryResolver(); + Map exampleMap = queryContext.getExampleMap(); - public SegmentResult buildSegment(Context context, Object coating) { - CoatingType coatingType = repository.getCoatingType(coating); - CoatingCriteria coatingCriteria = coatingType.newCriteria(coating); - Map> criteriaMap = coatingCriteria.getCriteriaMap(); - OrderBy orderBy = coatingCriteria.getOrderBy(); - Page page = coatingCriteria.getPage(); - - List mergedRepositories = coatingType.getMergedRepositories(); - Map segmentMap = new LinkedHashMap<>(mergedRepositories.size() * 4 / 3 + 1); - char letter = 'a'; - SelectSegment selectSegment = null; - List argSegments = new ArrayList<>(); - List args = new ArrayList<>(); + List mergedRepositories = queryResolver.getMergedRepositories(); + Map nodeMap = new LinkedHashMap<>(mergedRepositories.size() * 4 / 3 + 1); + SelectSegment selectSegment = new SelectSegment(); + List joinSegments = selectSegment.getJoinSegments(); for (MergedRepository mergedRepository : mergedRepositories) { - String lastAccessPath = mergedRepository.getLastAccessPath(); String absoluteAccessPath = mergedRepository.getAbsoluteAccessPath(); String relativeAccessPath = mergedRepository.getRelativeAccessPath(); - CommonRepository definedRepository = mergedRepository.getDefinedRepository(); CommonRepository executedRepository = mergedRepository.getExecutedRepository(); - BinderResolver binderResolver = definedRepository.getBinderResolver(); - - Map attachments = executedRepository.getAttachments(); - TableInfo tableInfo = (TableInfo) attachments.get(Keys.TABLE_INFO); - FieldExecutor fieldExecutor = (FieldExecutor) attachments.get(Keys.FIELD_EXECUTOR); + EntityEle entityEle = executedRepository.getEntityEle(); + EntityStoreInfo entityStoreInfo = AbstractContextRepository.getEntityStoreInfo(entityEle); + ExampleExecutor exampleExecutor = AbstractContextRepository.getExampleExecutor(entityEle); - String tableName = tableInfo.getTableName(); - String tableAlias = String.valueOf(letter); - letter = (char) (letter + 1); + String tableName = entityStoreInfo.getTableName(); + String tableAlias = selectSegment.generateTableAlias(); + Example example = exampleMap.computeIfAbsent(absoluteAccessPath, key -> new InnerExample(Collections.emptyList())); + exampleExecutor.convert(context, example); - List criteria = criteriaMap.computeIfAbsent(absoluteAccessPath, key -> Collections.emptyList()); - fieldExecutor.convertCriteria(context, criteria); - appendArguments(argSegments, args, tableAlias, criteria); + TableSegment tableSegment = new TableSegment(tableName, tableAlias, example.isNotEmpty(), new ArrayList<>(example.getCriteria().size())); + Node node = new Node(tableSegment, new ArrayList<>(4)); + nodeMap.put(relativeAccessPath, node); if ("/".equals(relativeAccessPath)) { - selectSegment = new SelectSegment(); - selectSegment.setReachable(true); - selectSegment.setDirtyQuery(!criteria.isEmpty()); - selectSegment.setDirectedSegments(new ArrayList<>(8)); - selectSegment.setDistinct(false); - selectSegment.setColumns(Collections.emptyList()); - selectSegment.setTableName(tableName); - selectSegment.setTableAlias(tableAlias); - selectSegment.setJoinSegments(new ArrayList<>()); - selectSegment.setArgSegments(argSegments); - segmentMap.put(relativeAccessPath, selectSegment); - - fieldExecutor.convertOrderBy(orderBy); + selectSegment.setTableSegment(tableSegment); } else { - JoinSegment joinSegment = new JoinSegment(); - joinSegment.setReachable(false); - joinSegment.setDirtyQuery(!criteria.isEmpty()); - joinSegment.setDirectedSegments(new ArrayList<>(4)); - joinSegment.setTableName(tableName); - joinSegment.setTableAlias(tableAlias); - - List onSegments = newOnSegments(segmentMap, lastAccessPath, binderResolver, tableAlias, joinSegment); - joinSegment.setOnSegments(onSegments); - - if (selectSegment != null) { - List joinSegments = selectSegment.getJoinSegments(); - joinSegments.add(joinSegment); + List onSegments = newOnSegments(nodeMap, mergedRepository, node); + if (onSegments.isEmpty()) { + nodeMap.remove(relativeAccessPath); + continue; } - - segmentMap.put(relativeAccessPath, joinSegment); + JoinSegment joinSegment = new JoinSegment(tableSegment, onSegments); + joinSegments.add(joinSegment); } - } - if (selectSegment != null) { - markReachableAndDirty(selectSegment); + addTableSegmentArgs(selectSegment, example, tableSegment); } - return new SegmentResult(letter, selectSegment, args, orderBy, page); + markTableSegmentJoin(nodeMap.get("/")); + selectSegment.filterTableSegments(); + return selectSegment; + } + + private List newOnSegments(Map nodeMap, MergedRepository mergedRepository, Node node) { + String lastAccessPath = mergedRepository.getLastAccessPath(); + CommonRepository definedRepository = mergedRepository.getDefinedRepository(); + BinderResolver binderResolver = definedRepository.getBinderResolver(); + List propertyBinders = binderResolver.getPropertyBinders(); + TableSegment tableSegment = node.getTableSegment(); + + List onSegments = new ArrayList<>(propertyBinders.size()); + for (PropertyBinder propertyBinder : propertyBinders) { + String relativeAccessPath = lastAccessPath + propertyBinder.getBelongAccessPath(); + Node targetNode = nodeMap.get(relativeAccessPath); + if (targetNode != null) { + TableSegment targetTableSegment = targetNode.getTableSegment(); + List children = targetNode.getChildren(); + if (!children.contains(node)) { + children.add(node); + } + OnSegment onSegment = new OnSegment(tableSegment.getTableAlias(), propertyBinder.getAlias(), + targetTableSegment.getTableAlias(), propertyBinder.getBindAlias()); + onSegments.add(onSegment); + } + } + return onSegments; } - private void appendArguments(List argSegments, - List args, - String tableAlias, - List criteria) { - for (Criterion criterion : criteria) { + private void addTableSegmentArgs(SelectSegment selectSegment, Example example, TableSegment tableSegment) { + List args = selectSegment.getArgs(); + String tableAlias = tableSegment.getTableAlias(); + List argSegments = tableSegment.getArgSegments(); + for (Criterion criterion : example.getCriteria()) { String property = criterion.getProperty(); String operator = CriterionUtils.getOperator(criterion); if (Operator.IS_NULL.equals(operator) || Operator.IS_NOT_NULL.equals(operator)) { @@ -152,48 +137,25 @@ public class SegmentBuilder { } } - private List newOnSegments(Map segmentMap, - String lastAccessPath, - BinderResolver binderResolver, - String tableAlias, - JoinSegment joinSegment) { - List propertyBinders = binderResolver.getPropertyBinders(); - List onSegments = new ArrayList<>(propertyBinders.size()); - - for (PropertyBinder propertyBinder : propertyBinders) { - String relativeAccessPath = lastAccessPath + propertyBinder.getBelongAccessPath(); - Segment segment = segmentMap.get(relativeAccessPath); - if (segment != null) { - String alias = propertyBinder.getAlias(); - String joinTableAlias = segment.getTableAlias(); - String bindAlias = propertyBinder.getBindAlias(); - - OnSegment onSegment = new OnSegment(); - onSegment.setDirectedSegments(Collections.singletonList(segment)); - onSegment.setTableAlias(tableAlias); - onSegment.setColumn(alias); - onSegment.setJoinTableAlias(joinTableAlias); - onSegment.setJoinColumn(bindAlias); - onSegments.add(onSegment); - - List directedSegments = segment.getDirectedSegments(); - if (!directedSegments.contains(joinSegment)) { - directedSegments.add(joinSegment); + private void markTableSegmentJoin(Node node) { + if (node != null) { + TableSegment tableSegment = node.getTableSegment(); + List children = node.getChildren(); + for (Node child : children) { + markTableSegmentJoin(child); + TableSegment childTableSegment = child.getTableSegment(); + if (childTableSegment.isJoin()) { + tableSegment.setJoin(true); } } } - return onSegments; } - private void markReachableAndDirty(Segment lastSegment) { - List directedSegments = lastSegment.getDirectedSegments(); - for (Segment directedSegment : directedSegments) { - directedSegment.setReachable(true); - markReachableAndDirty(directedSegment); - if (directedSegment.isDirtyQuery()) { - lastSegment.setDirtyQuery(true); - } - } + @Data + @AllArgsConstructor + public static class Node { + private TableSegment tableSegment; + private List children; } } diff --git a/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/impl/SQLExampleBuilder.java b/dorive-sql/src/main/java/com/gitee/dorive/sql/impl/SqlQueryExecutor.java similarity index 31% rename from dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/impl/SQLExampleBuilder.java rename to dorive-sql/src/main/java/com/gitee/dorive/sql/impl/SqlQueryExecutor.java index e07c27fe1e8d3fed6b8a6eaf84f2a83aadd33676..98271b65761039459396fda662ffa713f1ee0459 100644 --- a/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/impl/SQLExampleBuilder.java +++ b/dorive-sql/src/main/java/com/gitee/dorive/sql/impl/SqlQueryExecutor.java @@ -15,100 +15,127 @@ * limitations under the License. */ -package com.gitee.dorive.spring.boot.starter.impl; +package com.gitee.dorive.sql.impl; import cn.hutool.core.collection.CollUtil; -import com.baomidou.mybatisplus.extension.toolkit.SqlRunner; -import com.gitee.dorive.coating.api.ExampleBuilder; -import com.gitee.dorive.coating.entity.BuildExample; -import com.gitee.dorive.coating.repository.AbstractCoatingRepository; +import com.gitee.dorive.api.entity.element.EntityEle; import com.gitee.dorive.core.api.context.Context; +import com.gitee.dorive.core.entity.common.EntityStoreInfo; +import com.gitee.dorive.core.entity.executor.Example; +import com.gitee.dorive.core.entity.executor.InnerExample; import com.gitee.dorive.core.entity.executor.OrderBy; import com.gitee.dorive.core.entity.executor.Page; -import com.gitee.dorive.spring.boot.starter.entity.SegmentResult; -import com.gitee.dorive.spring.boot.starter.entity.SelectSegment; -import lombok.Data; +import com.gitee.dorive.core.entity.executor.Result; +import com.gitee.dorive.core.repository.AbstractContextRepository; +import com.gitee.dorive.query.entity.QueryContext; +import com.gitee.dorive.query.entity.QueryWrapper; +import com.gitee.dorive.query.entity.enums.ResultType; +import com.gitee.dorive.query.impl.executor.AbstractQueryExecutor; +import com.gitee.dorive.query.repository.AbstractQueryRepository; +import com.gitee.dorive.sql.api.SqlRunner; +import com.gitee.dorive.sql.entity.ArgSegment; +import com.gitee.dorive.sql.entity.SelectSegment; +import com.gitee.dorive.sql.entity.TableSegment; +import lombok.Getter; +import lombok.Setter; import java.util.ArrayList; import java.util.List; import java.util.Map; -@Data -public class SQLExampleBuilder implements ExampleBuilder { +@Getter +@Setter +public class SqlQueryExecutor extends AbstractQueryExecutor { - private final AbstractCoatingRepository repository; - private final SegmentBuilder segmentBuilder; + private SegmentBuilder segmentBuilder; + private SqlRunner sqlRunner; - public SQLExampleBuilder(AbstractCoatingRepository repository) { - this.repository = repository; - this.segmentBuilder = new SegmentBuilder(repository); + public SqlQueryExecutor(AbstractQueryRepository repository, SegmentBuilder segmentBuilder, SqlRunner sqlRunner) { + super(repository); + this.segmentBuilder = segmentBuilder; + this.sqlRunner = sqlRunner; } @Override - public BuildExample buildExample(Context context, Object coating) { - SegmentResult segmentResult = segmentBuilder.buildSegment(context, coating); - char letter = segmentResult.getLetter(); - SelectSegment selectSegment = segmentResult.getSelectSegment(); - List args = segmentResult.getArgs(); - OrderBy orderBy = segmentResult.getOrderBy(); - Page page = segmentResult.getPage(); - - BuildExample buildExample = new BuildExample(); - buildExample.setOrderBy(orderBy); - buildExample.setPage(page); - - if (selectSegment == null) { - throw new RuntimeException("Unable to build SQL statement!"); - } - if (selectSegment.getArgSegments().isEmpty()) { - return buildExample; - } - if (!selectSegment.isDirtyQuery()) { - return buildExample; + @SuppressWarnings("unchecked") + public Result executeQuery(QueryContext queryContext, QueryWrapper queryWrapper) { + Context context = queryContext.getContext(); + ResultType resultType = queryContext.getResultType(); + Example example = queryContext.getExample(); + + EntityEle entityEle = repository.getEntityEle(); + EntityStoreInfo entityStoreInfo = AbstractContextRepository.getEntityStoreInfo(entityEle); + String idColumn = entityStoreInfo.getIdColumn(); + + OrderBy orderBy = example.getOrderBy(); + Page page = example.getPage(); + + boolean needCount = queryContext.isNeedCount(); + Result emptyResult = queryContext.newEmptyResult(); + + SelectSegment selectSegment = segmentBuilder.buildSegment(queryContext); + char letter = selectSegment.getLetter(); + TableSegment tableSegment = selectSegment.getTableSegment(); + List argSegments = selectSegment.getArgSegments(); + List args = selectSegment.getArgs(); + if (!tableSegment.isJoin() || argSegments.isEmpty()) { + return super.executeQuery(queryContext, queryWrapper); } + String tableAlias = tableSegment.getTableAlias(); selectSegment.setDistinct(true); - List selectColumns = new ArrayList<>(2); - String tableAlias = selectSegment.getTableAlias(); - selectColumns.add(tableAlias + ".id"); - selectSegment.setColumns(selectColumns); + selectColumns.add(tableAlias + "." + idColumn); + selectSegment.setSelectColumns(selectColumns); + String selectSql = selectSegment.selectSql(); String fromWhereSql = selectSegment.fromWhereSql(); - if (page != null) { - String countSql = selectSegment.selectSql() + fromWhereSql; - long count = SqlRunner.db().selectCount("SELECT COUNT(1) FROM (" + countSql + ") " + letter, args.toArray()); - page.setTotal(count); - buildExample.setCountQueried(true); - if (count == 0) { - buildExample.setAbandoned(true); - return buildExample; + if (needCount) { + String countSql = selectSql + fromWhereSql; + long count = sqlRunner.selectCount("SELECT COUNT(*) AS total FROM (" + countSql + ") " + letter, args.toArray()); + if (count == 0L) { + return emptyResult; + } + if (resultType == ResultType.COUNT) { + return new Result<>(count); + + } else if (page != null) { + page.setTotal(count); } } + boolean rebuildSql = false; if (orderBy != null) { for (String property : orderBy.getProperties()) { - if (!"id".equals(property)) { + if (!idColumn.equals(property)) { selectColumns.add(tableAlias + "." + property); + rebuildSql = true; } } selectSegment.setOrderBy(orderBy.toString()); } + if (rebuildSql) { + selectSql = selectSegment.selectSql(); + } if (page != null) { selectSegment.setLimit(page.toString()); } - String selectSql = selectSegment.selectSql() + fromWhereSql + selectSegment.lastSql(); - List> resultMaps = SqlRunner.db().selectList(selectSql, args.toArray()); - List primaryKeys = CollUtil.map(resultMaps, map -> map.get("id"), true); + String sql = selectSql + fromWhereSql + selectSegment.lastSql(); + List> resultMaps = sqlRunner.selectList(sql, args.toArray()); + List primaryKeys = CollUtil.map(resultMaps, map -> map.get(idColumn), true); if (!primaryKeys.isEmpty()) { - buildExample.eq("id", primaryKeys); - } else { - buildExample.setAbandoned(true); + Example newExample = new InnerExample().in(entityEle.getIdName(), primaryKeys); + List entities = (List) repository.selectByExample(context, newExample); + if (page != null) { + page.setRecords(entities); + return new Result<>(page); + } else { + return new Result<>(entities); + } } - - return buildExample; + return emptyResult; } } diff --git a/dorive-sql/src/main/java/com/gitee/dorive/sql/impl/UnionExecutor.java b/dorive-sql/src/main/java/com/gitee/dorive/sql/impl/UnionExecutor.java new file mode 100644 index 0000000000000000000000000000000000000000..f9db3dba5b05f5510045593ca6f0a4b40dcf4a11 --- /dev/null +++ b/dorive-sql/src/main/java/com/gitee/dorive/sql/impl/UnionExecutor.java @@ -0,0 +1,162 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.gitee.dorive.sql.impl; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; +import com.gitee.dorive.core.api.context.Context; +import com.gitee.dorive.core.api.executor.Executor; +import com.gitee.dorive.core.entity.common.EntityStoreInfo; +import com.gitee.dorive.core.entity.executor.Criterion; +import com.gitee.dorive.core.entity.executor.Example; +import com.gitee.dorive.core.entity.executor.OrderBy; +import com.gitee.dorive.core.entity.executor.Page; +import com.gitee.dorive.core.entity.executor.Result; +import com.gitee.dorive.core.entity.executor.UnionExample; +import com.gitee.dorive.core.entity.operation.Query; +import com.gitee.dorive.core.impl.executor.AbstractProxyExecutor; +import com.gitee.dorive.sql.api.SqlRunner; +import lombok.Getter; +import lombok.Setter; +import org.apache.commons.lang3.StringUtils; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +@Getter +@Setter +public class UnionExecutor extends AbstractProxyExecutor { + + private SqlRunner sqlRunner; + private EntityStoreInfo entityStoreInfo; + + public UnionExecutor(Executor executor, SqlRunner sqlRunner, EntityStoreInfo entityStoreInfo) { + super(executor); + this.sqlRunner = sqlRunner; + this.entityStoreInfo = entityStoreInfo; + } + + @Override + public Result executeQuery(Context context, Query query) { + Example example = query.getExample(); + if (example instanceof UnionExample) { + UnionExample unionExample = (UnionExample) example; + String sql = buildSql(unionExample); + if (StringUtils.isNotBlank(sql)) { + List> resultMaps = sqlRunner.selectList(sql, (Object) null); + return buildResult(resultMaps); + } + } + return super.executeQuery(context, query); + } + + private String buildSql(UnionExample unionExample) { + if (unionExample.isEmpty()) { + return null; + } + String selectColumns = buildSelectColumns(unionExample); + String lastSql = buildLastSql(unionExample); + List sqls = buildSqls(unionExample, selectColumns, lastSql); + return StrUtil.join(" UNION ALL ", sqls); + } + + private String buildSelectColumns(Example example) { + String selectColumns = entityStoreInfo.getSelectColumns(); + List selectProps = example.getSelectProps(); + if (selectProps != null && !selectProps.isEmpty()) { + selectColumns = StrUtil.join(",", selectProps); + } + return selectColumns; + } + + private String buildLastSql(Example example) { + StringBuilder lastSql = new StringBuilder(); + OrderBy orderBy = example.getOrderBy(); + if (orderBy != null) { + lastSql.append(" ").append(orderBy); + } + Page page = example.getPage(); + if (page != null) { + lastSql.append(" ").append(page); + } + return lastSql.toString(); + } + + private List buildSqls(UnionExample unionExample, String selectColumns, String lastSql) { + List examples = unionExample.getExamples(); + List sqls = new ArrayList<>(examples.size()); + Example example = examples.get(0); + String sql = doBuildSql(false, selectColumns, example, lastSql); + sqls.add(sql); + for (int index = 1; index < examples.size(); index++) { + Example nextExample = examples.get(index); + String nextSql = doBuildSql(true, selectColumns, nextExample, lastSql); + sqls.add(nextSql); + } + return sqls; + } + + private String doBuildSql(boolean hasBrackets, String selectColumns, Example example, String lastSql) { + StringBuilder sql = new StringBuilder(); + if (hasBrackets) { + sql.append("("); + } + String template = "SELECT %s,%s FROM %s WHERE %s"; + String selectSuffix = example.getSelectSuffix(); + String tableName = entityStoreInfo.getTableName(); + String criteria = CollUtil.join(example.getCriteria(), " AND ", Criterion::toString); + String selectSql = String.format(template, selectColumns, selectSuffix, tableName, criteria); + sql.append(selectSql); + sql.append(lastSql); + if (hasBrackets) { + sql.append(")"); + } + return sql.toString(); + } + + @SuppressWarnings("unchecked") + private Result buildResult(List> resultMaps) { + Map> idResultMapMapping = new LinkedHashMap<>(resultMaps.size() * 4 / 3 + 1); + for (Map resultMap : resultMaps) { + Object id = resultMap.get(entityStoreInfo.getIdColumn()); + Object row = resultMap.get("$row"); + if (id == null || row == null) { + continue; + } + String idStr = id.toString(); + String rowStr = row.toString(); + if (!idResultMapMapping.containsKey(idStr)) { + idResultMapMapping.put(idStr, resultMap); + } else { + Map existResultMap = idResultMapMapping.get(idStr); + List existRows = (List) existResultMap.computeIfAbsent("$rows", key -> new ArrayList<>(4)); + if (existRows.isEmpty()) { + Object existRow = existResultMap.get("$row"); + if (existRow != null) { + existRows.add(existRow.toString()); + } + } + existRows.add(rowStr); + } + } + return new Result<>(null, new ArrayList<>(idResultMapMapping.values())); + } + +} diff --git a/dorive-web/pom.xml b/dorive-web/pom.xml index f46594f39458b709046a45dd43ee2a6b07c1bc70..d0151dc17fe433bcecf7ee4c8026d0b71823f00a 100644 --- a/dorive-web/pom.xml +++ b/dorive-web/pom.xml @@ -6,17 +6,13 @@ com.gitee.digital-engine dorive - 3.4.3.1 + 3.4.3.3 dorive-web org.springframework.boot - spring-boot-starter - - - com.fasterxml.jackson.core - jackson-annotations + spring-boot-starter-web org.projectlombok diff --git a/dorive-web/src/main/java/com/gitee/dorive/web/advice/ParameterControllerAdvice.java b/dorive-web/src/main/java/com/gitee/dorive/web/advice/ParameterControllerAdvice.java new file mode 100644 index 0000000000000000000000000000000000000000..db8e69e95af4b77565773a44639440136e0e6bee --- /dev/null +++ b/dorive-web/src/main/java/com/gitee/dorive/web/advice/ParameterControllerAdvice.java @@ -0,0 +1,39 @@ +package com.gitee.dorive.web.advice; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.NumberUtil; +import org.apache.commons.lang3.StringUtils; +import org.springframework.web.bind.WebDataBinder; +import org.springframework.web.bind.annotation.InitBinder; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +import java.beans.PropertyEditorSupport; +import java.util.Date; + +@RestControllerAdvice +public class ParameterControllerAdvice { + + @InitBinder + public void initBinder(WebDataBinder webDataBinder) { + webDataBinder.registerCustomEditor(Date.class, new PropertyEditorSupport() { + @Override + public void setAsText(String text) { + if (StringUtils.isBlank(text)) { + return; + } + text = text.trim(); + Object value; + boolean isNumber = NumberUtil.isNumber(text); + if (isNumber) { + long number = NumberUtil.parseLong(text); + int multi = NumberUtil.pow(10, 13 - String.valueOf(number).length()).intValue(); + value = DateUtil.date(number * multi); + } else { + value = DateUtil.parseDateTime(text); + } + setValue(value); + } + }); + } + +} diff --git a/dorive-web/src/main/java/com/gitee/dorive/web/config/DoriveWebConfiguration.java b/dorive-web/src/main/java/com/gitee/dorive/web/config/DoriveWebConfiguration.java new file mode 100644 index 0000000000000000000000000000000000000000..5ec57b8aa619a4c56a1659c648e34529a9d3c1a3 --- /dev/null +++ b/dorive-web/src/main/java/com/gitee/dorive/web/config/DoriveWebConfiguration.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.gitee.dorive.web.config; + +import com.gitee.dorive.web.advice.ParameterControllerAdvice; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.annotation.Order; + +@Order(-100) +@Configuration +public class DoriveWebConfiguration { + + @Bean("parameterControllerAdvice") + public static ParameterControllerAdvice parameterControllerAdvice() { + return new ParameterControllerAdvice(); + } + +} diff --git a/dorive-web/src/main/resources/META-INF.spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/dorive-web/src/main/resources/META-INF.spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 0000000000000000000000000000000000000000..9cee1bae30b4c7fb55dfe7df9bd5212460b741be --- /dev/null +++ b/dorive-web/src/main/resources/META-INF.spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +com.gitee.dorive.web.config.DoriveWebConfiguration \ No newline at end of file diff --git a/dorive-web/src/main/resources/META-INF/spring.factories b/dorive-web/src/main/resources/META-INF/spring.factories new file mode 100644 index 0000000000000000000000000000000000000000..388ace2511220b8ba19b1169712dfc3c3fb7cee2 --- /dev/null +++ b/dorive-web/src/main/resources/META-INF/spring.factories @@ -0,0 +1,2 @@ +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ + com.gitee.dorive.web.config.DoriveWebConfiguration \ No newline at end of file diff --git a/pom.xml b/pom.xml index 1c5b1e75411346bef619bfdccc9df4cc2143318a..c223ef9a896d2934145dd078d8af57fdd7605cf0 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ 4.0.0 com.gitee.digital-engine dorive - 3.4.3.1 + 3.4.3.3 pom @@ -29,15 +29,17 @@ - dorive-injection + dorive-inject dorive-env dorive-web dorive-proxy dorive-api dorive-core dorive-event - dorive-coating + dorive-query dorive-ref + dorive-sql + dorive-mybatis-plus dorive-spring-boot-starter @@ -56,9 +58,14 @@ 2.7.8 - com.fasterxml.jackson.core - jackson-annotations - 2.13.4 + org.springframework.boot + spring-boot-starter-web + 2.7.8 + + + org.springframework + spring-tx + 5.3.9 org.projectlombok