diff --git a/dorive-api/pom.xml b/dorive-api/pom.xml index 89f533b286e3bda889b9bdf3777b349e01b2a7c3..4e2324b0f253c23ce4bf8e2b4c560571607dad14 100644 --- a/dorive-api/pom.xml +++ b/dorive-api/pom.xml @@ -6,7 +6,7 @@ com.gitee.digital-engine dorive - 3.5.0.3 + 3.5.0.4 dorive-api diff --git a/dorive-api/src/main/java/com/gitee/dorive/api/annotation/core/Aggregate.java b/dorive-api/src/main/java/com/gitee/dorive/api/annotation/core/Aggregate.java index d4146e859b7fb860970f1d546ee8fe03dca8f7be..6e67f6f3559eaa05c6d9b23957d4cadd21efa2d2 100644 --- a/dorive-api/src/main/java/com/gitee/dorive/api/annotation/core/Aggregate.java +++ b/dorive-api/src/main/java/com/gitee/dorive/api/annotation/core/Aggregate.java @@ -46,7 +46,7 @@ public @interface Aggregate { * @see Entity */ @AliasFor(annotation = Entity.class) - Class source() default Object.class; + Class dataSource() default Object.class; /** * @see Entity diff --git a/dorive-api/src/main/java/com/gitee/dorive/api/annotation/core/Entity.java b/dorive-api/src/main/java/com/gitee/dorive/api/annotation/core/Entity.java index bdcab97ff057a65c2f526dcdb192f6d77e2253aa..07fde6fba9c4490366ad476d9d9e8601c6ba697b 100644 --- a/dorive-api/src/main/java/com/gitee/dorive/api/annotation/core/Entity.java +++ b/dorive-api/src/main/java/com/gitee/dorive/api/annotation/core/Entity.java @@ -34,9 +34,9 @@ public @interface Entity { String name() default ""; /** - * 数据来源 + * 数据源 */ - Class source() default Object.class; + Class dataSource() default Object.class; /** * 实体工厂 diff --git a/dorive-api/src/main/java/com/gitee/dorive/api/annotation/core/Repository.java b/dorive-api/src/main/java/com/gitee/dorive/api/annotation/core/Repository.java index 8a28c5da909e8e8d0d2461aa5dfe66491f5312b4..2e747edba484d4b0e2fe8ef56eb6b4d6df4e7b26 100644 --- a/dorive-api/src/main/java/com/gitee/dorive/api/annotation/core/Repository.java +++ b/dorive-api/src/main/java/com/gitee/dorive/api/annotation/core/Repository.java @@ -35,4 +35,10 @@ public @interface Repository { @AliasFor(annotation = Component.class) String value() default ""; + Class[] derived() default {}; + + Class[] events() default {}; + + Class[] queries() default {}; + } diff --git a/dorive-api/src/main/java/com/gitee/dorive/api/annotation/event/EnableEvent.java b/dorive-api/src/main/java/com/gitee/dorive/api/annotation/event/EnableEvent.java deleted file mode 100644 index aa885bc6a25ffbd8018ed44591fdc942bf830ee3..0000000000000000000000000000000000000000 --- a/dorive-api/src/main/java/com/gitee/dorive/api/annotation/event/EnableEvent.java +++ /dev/null @@ -1,32 +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.api.annotation.event; - -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; - -@Inherited -@Documented -@Target(ElementType.TYPE) -@Retention(RetentionPolicy.RUNTIME) -public @interface EnableEvent { -} diff --git a/dorive-api/src/main/java/com/gitee/dorive/api/entity/core/FieldEntityDefinition.java b/dorive-api/src/main/java/com/gitee/dorive/api/entity/core/FieldEntityDefinition.java index b4f45fbd67bac93c9413a2ec68c4defa9c67b32d..6e23921e3bd4bf8dd6c526a4995b98baaddcf3d2 100644 --- a/dorive-api/src/main/java/com/gitee/dorive/api/entity/core/FieldEntityDefinition.java +++ b/dorive-api/src/main/java/com/gitee/dorive/api/entity/core/FieldEntityDefinition.java @@ -31,6 +31,10 @@ public class FieldEntityDefinition extends EntityDefinition { private List bindingDefs; private OrderDef orderDef; + public java.lang.reflect.Field getJavaField() { + return field != null ? field.getField() : null; + } + public boolean isCollection() { return field != null && field.isCollection(); } diff --git a/dorive-api/src/main/java/com/gitee/dorive/api/entity/core/def/EntityDef.java b/dorive-api/src/main/java/com/gitee/dorive/api/entity/core/def/EntityDef.java index 43ba82e2060225197a9d1826fa4ca81cc5df8a12..bc3e65237ec1bd7e65648568904044717798e9ed 100644 --- a/dorive-api/src/main/java/com/gitee/dorive/api/entity/core/def/EntityDef.java +++ b/dorive-api/src/main/java/com/gitee/dorive/api/entity/core/def/EntityDef.java @@ -32,7 +32,7 @@ import java.util.Map; @AllArgsConstructor public class EntityDef { private String name; - private Class source; + private Class dataSource; private Class factory; private Class repository; private int priority; diff --git a/dorive-api/src/main/java/com/gitee/dorive/api/entity/query/def/EnableQueryDef.java b/dorive-api/src/main/java/com/gitee/dorive/api/entity/core/def/RepositoryDef.java similarity index 59% rename from dorive-api/src/main/java/com/gitee/dorive/api/entity/query/def/EnableQueryDef.java rename to dorive-api/src/main/java/com/gitee/dorive/api/entity/core/def/RepositoryDef.java index 5d2c8afe2ebb081fa274dec987e8b72a68e799fd..45acb40630d96904d9f7af166b5610750a0a5ae3 100644 --- a/dorive-api/src/main/java/com/gitee/dorive/api/entity/query/def/EnableQueryDef.java +++ b/dorive-api/src/main/java/com/gitee/dorive/api/entity/core/def/RepositoryDef.java @@ -15,9 +15,9 @@ * limitations under the License. */ -package com.gitee.dorive.api.entity.query.def; +package com.gitee.dorive.api.entity.core.def; -import com.gitee.dorive.api.annotation.query.EnableQuery; +import com.gitee.dorive.api.annotation.core.Repository; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @@ -28,15 +28,21 @@ import java.lang.reflect.AnnotatedElement; @Data @NoArgsConstructor @AllArgsConstructor -public class EnableQueryDef { +public class RepositoryDef { + private String value; + private Class[] derived; + private Class[] events; private Class[] queries; - public static EnableQueryDef fromElement(AnnotatedElement element) { - EnableQuery enableQuery = AnnotatedElementUtils.getMergedAnnotation(element, EnableQuery.class); - if (enableQuery != null) { - EnableQueryDef enableQueryDef = new EnableQueryDef(); - enableQueryDef.setQueries(enableQuery.queries()); - return enableQueryDef; + public static RepositoryDef fromElement(AnnotatedElement element) { + Repository repository = AnnotatedElementUtils.getMergedAnnotation(element, Repository.class); + if (repository != null) { + RepositoryDef repositoryDef = new RepositoryDef(); + repositoryDef.setValue(repository.value()); + repositoryDef.setDerived(repository.derived()); + repositoryDef.setEvents(repository.events()); + repositoryDef.setQueries(repository.queries()); + return repositoryDef; } return null; } diff --git a/dorive-api/src/main/java/com/gitee/dorive/api/impl/core/EntityDefinitionResolver.java b/dorive-api/src/main/java/com/gitee/dorive/api/impl/core/EntityDefinitionResolver.java index 911c2e32bb94a2651d8e027e16b4d4909e9840f4..d705c6ea80c02523c95639d0a28b765ada6f3b23 100644 --- a/dorive-api/src/main/java/com/gitee/dorive/api/impl/core/EntityDefinitionResolver.java +++ b/dorive-api/src/main/java/com/gitee/dorive/api/impl/core/EntityDefinitionResolver.java @@ -156,9 +156,9 @@ public class EntityDefinitionResolver { if (StringUtils.isNotBlank(name)) { newEntityDef.setName(name); } - Class source = entityAnnotation.source(); - if (source != Object.class) { - newEntityDef.setSource(source); + Class dataSource = entityAnnotation.dataSource(); + if (dataSource != Object.class) { + newEntityDef.setDataSource(dataSource); } Class factory = entityAnnotation.factory(); if (factory != Object.class) { diff --git a/dorive-core/pom.xml b/dorive-core/pom.xml index 1228baa4145b20edadbf5ecd9f83c840e0de8571..c79b5973c055f84bdb90d4afd5b03cccce02374f 100644 --- a/dorive-core/pom.xml +++ b/dorive-core/pom.xml @@ -6,7 +6,7 @@ com.gitee.digital-engine dorive - 3.5.0.3 + 3.5.0.4 dorive-core diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/api/context/Options.java b/dorive-core/src/main/java/com/gitee/dorive/core/api/context/Options.java index 87fb517bd0127501d160d83128aa281cc202057d..81e96e13528a336a2f338a3a128d3cdcef89fc0a 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/api/context/Options.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/api/context/Options.java @@ -18,14 +18,14 @@ package com.gitee.dorive.core.api.context; import com.gitee.dorive.core.entity.context.EnumOptions; -import com.gitee.dorive.core.entity.enums.SelectType; +import com.gitee.dorive.core.entity.enums.MatcherType; import java.util.Map; public interface Options { - Options ROOT = new EnumOptions(SelectType.class, SelectType.ROOT); - Options ALL = new EnumOptions(SelectType.class, SelectType.ALL); + Options ROOT = new EnumOptions(MatcherType.class, MatcherType.ROOT); + Options ALL = new EnumOptions(MatcherType.class, MatcherType.ALL); Map, Object> getOptions(); diff --git a/dorive-api/src/main/java/com/gitee/dorive/api/constant/event/Event.java b/dorive-core/src/main/java/com/gitee/dorive/core/api/executor/EntityOpHandler.java similarity index 76% rename from dorive-api/src/main/java/com/gitee/dorive/api/constant/event/Event.java rename to dorive-core/src/main/java/com/gitee/dorive/core/api/executor/EntityOpHandler.java index 903ad9e1343ffddc303537829acc15f204af10d1..0269f3f564efc082992fd4e687277432ec889446 100644 --- a/dorive-api/src/main/java/com/gitee/dorive/api/constant/event/Event.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/api/executor/EntityOpHandler.java @@ -15,10 +15,13 @@ * limitations under the License. */ -package com.gitee.dorive.api.constant.event; +package com.gitee.dorive.core.api.executor; + +import com.gitee.dorive.core.api.context.Context; +import com.gitee.dorive.core.entity.operation.EntityOp; + +public interface EntityOpHandler { + + long handle(Context context, EntityOp entityOp); -public interface Event { - String INSERT = "INSERT"; - String UPDATE = "UPDATE"; - String DELETE = "DELETE"; } 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 9f9e444df3ecb2d7000af44544aba21a112d4028..618d646e7af5da6c9f98898547f735d33ff43c6a 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 @@ -19,67 +19,44 @@ package com.gitee.dorive.core.entity.context; import com.gitee.dorive.core.api.context.Context; import com.gitee.dorive.core.api.context.Options; +import lombok.AllArgsConstructor; import lombok.Getter; +import lombok.NoArgsConstructor; import lombok.Setter; -import java.util.LinkedHashMap; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; @Getter @Setter -public abstract class AbstractContext extends LinkedHashMap implements Context { +@NoArgsConstructor +@AllArgsConstructor +public abstract class AbstractContext extends AbstractOptions implements Context { - protected Map, Object> options = new LinkedHashMap<>(4); - - public AbstractContext() { - super(8); - } + private Map attachments = new ConcurrentHashMap<>(8); public AbstractContext(Options options) { - this(); - this.options.putAll(options.getOptions()); - } - - public AbstractContext(Context anotherContext) { - this(); - this.options.putAll(anotherContext.getOptions()); - putAll(anotherContext.getAttachments()); - } - - @Override - public void setOption(Class type, T value) { - options.put(type, value); + super(options); } - @Override - @SuppressWarnings("unchecked") - public T getOption(Class type) { - return (T) options.get(type); - } - - @Override - public void removeOption(Class type) { - options.remove(type); - } - - @Override - public Map getAttachments() { - return this; + public AbstractContext(Context context) { + super(context); + this.attachments.putAll(context.getAttachments()); } @Override public void setAttachment(String name, Object value) { - put(name, value); + attachments.put(name, value); } @Override public Object getAttachment(String name) { - return get(name); + return attachments.get(name); } @Override public void removeAttachment(String name) { - remove(name); + attachments.remove(name); } } diff --git a/dorive-event/src/main/java/com/gitee/dorive/event/impl/listener/adapter/RouteListenerAdapter.java b/dorive-core/src/main/java/com/gitee/dorive/core/entity/context/AbstractOptions.java similarity index 49% rename from dorive-event/src/main/java/com/gitee/dorive/event/impl/listener/adapter/RouteListenerAdapter.java rename to dorive-core/src/main/java/com/gitee/dorive/core/entity/context/AbstractOptions.java index cd1f7023734848557dab91a8ef8be2460ecbc708..65a85afdd716e1a09103f7994e94d1c7fec3244f 100644 --- a/dorive-event/src/main/java/com/gitee/dorive/event/impl/listener/adapter/RouteListenerAdapter.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/entity/context/AbstractOptions.java @@ -15,35 +15,43 @@ * limitations under the License. */ -package com.gitee.dorive.event.impl.listener.adapter; +package com.gitee.dorive.core.entity.context; -import cn.hutool.core.util.ArrayUtil; -import com.gitee.dorive.api.entity.event.def.ListenerDef; -import com.gitee.dorive.event.api.EntityEventListener; -import com.gitee.dorive.event.entity.EntityEvent; +import com.gitee.dorive.core.api.context.Options; import lombok.AllArgsConstructor; -import lombok.Data; +import lombok.Getter; import lombok.NoArgsConstructor; -import lombok.extern.slf4j.Slf4j; +import lombok.Setter; -@Data -@Slf4j +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +@Getter +@Setter @NoArgsConstructor @AllArgsConstructor -public class RouteListenerAdapter implements EntityEventListener { +public abstract class AbstractOptions implements Options { + + private Map, Object> options = new ConcurrentHashMap<>(4); - private ListenerDef listenerDef; - private EntityEventListener entityEventListener; + public AbstractOptions(Options options) { + this.options.putAll(options.getOptions()); + } + + @Override + public void setOption(Class type, T value) { + options.put(type, value); + } + + @Override + @SuppressWarnings("unchecked") + public T getOption(Class type) { + return (T) options.get(type); + } @Override - public void onEntityEvent(EntityEvent entityEvent) { - boolean matchPublisher = ArrayUtil.contains(listenerDef.getPublishers(), entityEvent.getPublisher()); - boolean matchEvent = ArrayUtil.contains(listenerDef.getEvents(), entityEvent.getName()); - boolean matchOnlyRoot = !listenerDef.isOnlyRoot() || entityEvent.isRoot(); - - if (matchPublisher && matchEvent && matchOnlyRoot) { - entityEventListener.onEntityEvent(entityEvent); - } + public void removeOption(Class type) { + options.remove(type); } } diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/entity/context/AbstractProxyContext.java b/dorive-core/src/main/java/com/gitee/dorive/core/entity/context/AbstractProxyContext.java new file mode 100644 index 0000000000000000000000000000000000000000..35e1c81f706b3a1f0f2da4ff881514c420a6b82b --- /dev/null +++ b/dorive-core/src/main/java/com/gitee/dorive/core/entity/context/AbstractProxyContext.java @@ -0,0 +1,74 @@ +/* + * 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.context; + +import com.gitee.dorive.core.api.context.Context; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; + +import java.util.Map; + +@Getter +@Setter +@AllArgsConstructor +public abstract class AbstractProxyContext implements Context { + + protected Context context; + + @Override + public Map, Object> getOptions() { + return context.getOptions(); + } + + @Override + public void setOption(Class type, T value) { + context.setOption(type, value); + } + + @Override + public T getOption(Class type) { + return context.getOption(type); + } + + @Override + public void removeOption(Class type) { + context.removeOption(type); + } + + @Override + public Map getAttachments() { + return context.getAttachments(); + } + + @Override + public void setAttachment(String name, Object value) { + context.setAttachment(name, value); + } + + @Override + public Object getAttachment(String name) { + return context.getAttachment(name); + } + + @Override + public void removeAttachment(String name) { + context.removeAttachment(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 9174f4454e6a43c4cf5a68006bdd7e11e221d77c..d2466535dfcf32e4305600f8c5fb118924c289b4 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 @@ -28,8 +28,8 @@ public class BoundedContext extends AbstractContext { super(options); } - public BoundedContext(Context anotherContext) { - super(anotherContext); + public BoundedContext(Context context) { + super(context); } } 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 b70e6f8a96899575d669e1481836631afe8866ce..d7982a48453cb3c3e4fc0ad61c75dea7d9933e29 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 @@ -28,8 +28,8 @@ public class InnerContext extends AbstractContext { super(options); } - public InnerContext(Context anotherContext) { - super(anotherContext); + public InnerContext(Context context) { + super(context); } } diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/entity/enums/SelectType.java b/dorive-core/src/main/java/com/gitee/dorive/core/entity/enums/MatcherType.java similarity index 97% rename from dorive-core/src/main/java/com/gitee/dorive/core/entity/enums/SelectType.java rename to dorive-core/src/main/java/com/gitee/dorive/core/entity/enums/MatcherType.java index e96e7bac7b410fd16ee0391a068877c1c5f65ef4..647121949f072f522acabed1bc8cef1cbdddf206 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/entity/enums/SelectType.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/entity/enums/MatcherType.java @@ -17,7 +17,7 @@ package com.gitee.dorive.core.entity.enums; -public enum SelectType { +public enum MatcherType { NONE, ROOT, ALL, diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/impl/context/AbstractSelector.java b/dorive-core/src/main/java/com/gitee/dorive/core/impl/context/AbstractSelector.java index 9b6bff638c2624a67bfd63ae4870fda4a9d4236c..aa72cbb52bdb539c5a4143527d8b46e8cc5e0937 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/impl/context/AbstractSelector.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/impl/context/AbstractSelector.java @@ -18,39 +18,14 @@ package com.gitee.dorive.core.impl.context; import com.gitee.dorive.core.api.context.Selector; -import com.gitee.dorive.core.entity.enums.SelectType; +import com.gitee.dorive.core.entity.context.AbstractOptions; +import com.gitee.dorive.core.entity.enums.MatcherType; -import java.util.LinkedHashMap; -import java.util.Map; - -public abstract class AbstractSelector implements Selector { - - private final Map, Object> options = new LinkedHashMap<>(3); +public abstract class AbstractSelector extends AbstractOptions implements Selector { public AbstractSelector() { - this.options.put(SelectType.class, SelectType.SELECTOR); - this.options.put(Selector.class, this); - } - - @Override - public Map, Object> getOptions() { - return options; - } - - @Override - public void setOption(Class type, T value) { - throw new UnsupportedOperationException(); - } - - @Override - @SuppressWarnings("unchecked") - public T getOption(Class type) { - return (T) options.get(type); - } - - @Override - public void removeOption(Class type) { - throw new UnsupportedOperationException(); + setOption(MatcherType.class, MatcherType.SELECTOR); + setOption(Selector.class, this); } } 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/AdaptiveMatcher.java similarity index 72% rename from dorive-core/src/main/java/com/gitee/dorive/core/impl/context/SelectTypeMatcher.java rename to dorive-core/src/main/java/com/gitee/dorive/core/impl/context/AdaptiveMatcher.java index cd22d00c3f65ae305ce9267a0c2e43b85287c607..1b3ceab8840ce77d92c094ebfa5d00bc46abdddd 100644 --- 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/AdaptiveMatcher.java @@ -20,7 +20,7 @@ package com.gitee.dorive.core.impl.context; import com.gitee.dorive.core.api.context.Matcher; import com.gitee.dorive.core.api.context.Options; import com.gitee.dorive.core.api.context.Selector; -import com.gitee.dorive.core.entity.enums.SelectType; +import com.gitee.dorive.core.entity.enums.MatcherType; import com.gitee.dorive.core.repository.CommonRepository; import lombok.Getter; import lombok.Setter; @@ -34,24 +34,24 @@ import java.util.Set; */ @Getter @Setter -public class SelectTypeMatcher implements Matcher { +public class AdaptiveMatcher implements Matcher { private CommonRepository repository; - private Map matcherMap = new LinkedHashMap<>(8); + private Map matcherTypeMatcherMap = new LinkedHashMap<>(6); - public SelectTypeMatcher(CommonRepository repository) { + public AdaptiveMatcher(CommonRepository repository) { this.repository = repository; - this.matcherMap.put(SelectType.NONE, options -> false); - this.matcherMap.put(SelectType.ROOT, options -> repository.isRoot()); - this.matcherMap.put(SelectType.ALL, options -> true); - this.matcherMap.put(SelectType.SELECTOR, new SelectorMatcher()); + this.matcherTypeMatcherMap.put(MatcherType.NONE, options -> false); + this.matcherTypeMatcherMap.put(MatcherType.ROOT, options -> repository.isRoot()); + this.matcherTypeMatcherMap.put(MatcherType.ALL, options -> true); + this.matcherTypeMatcherMap.put(MatcherType.SELECTOR, new SelectorMatcher()); } @Override public boolean matches(Options options) { - SelectType selectType = options.getOption(SelectType.class); - if (selectType != null) { - Matcher matcher = matcherMap.get(selectType); + MatcherType matcherType = options.getOption(MatcherType.class); + if (matcherType != null) { + Matcher matcher = matcherTypeMatcherMap.get(matcherType); if (matcher != null) { return matcher.matches(options); } diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/impl/executor/ContextExecutor.java b/dorive-core/src/main/java/com/gitee/dorive/core/impl/executor/ContextExecutor.java index f89a8ad9560981a9cc72dab2f2e8799a628db46b..1f41721a7877e09d5f912970c79909bc1624839e 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/impl/executor/ContextExecutor.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/impl/executor/ContextExecutor.java @@ -18,23 +18,15 @@ package com.gitee.dorive.core.impl.executor; import cn.hutool.core.lang.Assert; -import cn.hutool.core.lang.Pair; -import com.gitee.dorive.api.entity.core.EntityElement; import com.gitee.dorive.core.api.context.Context; import com.gitee.dorive.core.api.executor.EntityHandler; +import com.gitee.dorive.core.api.executor.EntityOpHandler; import com.gitee.dorive.core.entity.executor.Result; import com.gitee.dorive.core.entity.operation.EntityOp; import com.gitee.dorive.core.entity.operation.Operation; import com.gitee.dorive.core.entity.operation.cop.Query; -import com.gitee.dorive.core.entity.operation.eop.Delete; -import com.gitee.dorive.core.entity.operation.eop.Insert; -import com.gitee.dorive.core.entity.operation.eop.InsertOrUpdate; -import com.gitee.dorive.core.entity.operation.eop.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 com.gitee.dorive.core.util.CollectionUtils; import lombok.Getter; import lombok.Setter; @@ -42,14 +34,16 @@ import java.util.List; @Getter @Setter -public class ContextExecutor extends AbstractExecutor { +public class ContextExecutor extends AbstractExecutor implements EntityHandler, EntityOpHandler { private final AbstractContextRepository repository; private final EntityHandler entityHandler; + private final EntityOpHandler entityOpHandler; - public ContextExecutor(AbstractContextRepository repository, EntityHandler entityHandler) { + public ContextExecutor(AbstractContextRepository repository, EntityHandler entityHandler, EntityOpHandler entityOpHandler) { this.repository = repository; this.entityHandler = entityHandler; + this.entityOpHandler = entityOpHandler; } @Override @@ -60,27 +54,16 @@ public class ContextExecutor extends AbstractExecutor { Result result = rootRepository.executeQuery(context, query); List entities = result.getRecords(); if (!entities.isEmpty()) { - populate(context, entities); + handle(context, entities); } return result; } return Result.emptyResult(query); } - public void populate(Context context, List entities) { - DerivedResolver derivedResolver = repository.getDerivedResolver(); - if (!derivedResolver.hasDerived()) { - entityHandler.handle(context, entities); - } else { - for (Pair, List> pair : derivedResolver.distribute(entities)) { - if (pair.getKey() == this.repository) { // 避免自循环 - entityHandler.handle(context, pair.getValue()); - } else { - ContextExecutor contextExecutor = (ContextExecutor) pair.getKey().getExecutor(); - contextExecutor.populate(context, pair.getValue()); - } - } - } + @Override + public long handle(Context context, List entities) { + return entityHandler.handle(context, entities); } @Override @@ -93,147 +76,12 @@ public class ContextExecutor extends AbstractExecutor { EntityOp entityOp = (EntityOp) operation; List entities = entityOp.getEntities(); Assert.notEmpty(entities, "The entities cannot be empty!"); - - int totalCount = 0; - for (Pair, List> pair : repository.getDerivedResolver().distribute(entities)) { - ContextExecutor contextExecutor = (ContextExecutor) pair.getKey().getExecutor(); - if (operation instanceof Insert) { - Insert insert = new Insert(pair.getValue()); - totalCount += contextExecutor.executeInsert(context, insert); - - } else if (operation instanceof Update) { - Update update = new Update(pair.getValue()); - totalCount += contextExecutor.executeUpdateOrDelete(context, update); - - } else if (operation instanceof Delete) { - Delete delete = new Delete(pair.getValue()); - totalCount += contextExecutor.executeUpdateOrDelete(context, delete); - - } else if (operation instanceof InsertOrUpdate) { - OperationFactory operationFactory = repository.getOperationFactory(); - InsertOrUpdate insertOrUpdate = operationFactory.buildInsertOrUpdate(pair.getValue()); - totalCount += contextExecutor.executeInsertOrUpdate(context, insertOrUpdate); - } - } - return totalCount; - } - - public int executeInsert(Context context, Insert insert) { - int totalCount = 0; - for (CommonRepository repository : this.repository.getOrderedRepositories()) { - if (repository.isRoot()) { - if (insert.isNotIgnoreRoot()) { - if (repository.matches(context) || insert.isIncludeRoot()) { - totalCount += repository.execute(context, insert); - } - } - } else { - boolean isMatch = repository.matches(context); - boolean isAggregated = repository.isAggregated(); - if (!isMatch && !isAggregated) { - continue; - } - List rootEntities = insert.getEntities(); - for (Object rootEntity : rootEntities) { - EntityElement entityElement = repository.getEntityElement(); - Object targetEntity = entityElement.getValue(rootEntity); - if (targetEntity == null) { - continue; - } - List entities = CollectionUtils.toList(targetEntity); - if (entities.isEmpty()) { - continue; - } - if (isMatch) { - repository.getBoundValue(context, rootEntity, entities); - } - Operation operation = new Insert(entities); - operation.switchRoot(isMatch); - totalCount += repository.execute(context, operation); - if (entities.size() == 1) { - repository.setBoundId(context, rootEntity, entities.get(0)); - } - } - } - } - return totalCount; - } - - public int executeUpdateOrDelete(Context context, EntityOp entityOp) { - int totalCount = 0; - for (CommonRepository repository : this.repository.getOrderedRepositories()) { - if (repository.isRoot()) { - if (entityOp.isNotIgnoreRoot()) { - if (repository.matches(context) || entityOp.isIncludeRoot()) { - totalCount += repository.execute(context, entityOp); - } - } - } else { - boolean isMatch = repository.matches(context); - boolean isAggregated = repository.isAggregated(); - if (!isMatch && !isAggregated) { - continue; - } - List rootEntities = entityOp.getEntities(); - for (Object rootEntity : rootEntities) { - EntityElement entityElement = repository.getEntityElement(); - Object targetEntity = entityElement.getValue(rootEntity); - if (targetEntity == null) { - continue; - } - List entities = CollectionUtils.toList(targetEntity); - if (entities.isEmpty()) { - continue; - } - Operation operation = entityOp instanceof Update ? new Update(entities) : new Delete(entities); - operation.switchRoot(isMatch); - totalCount += repository.execute(context, operation); - } - } - } - return totalCount; + return (int) handle(context, entityOp); } - public int executeInsertOrUpdate(Context context, InsertOrUpdate insertOrUpdate) { - int totalCount = 0; - for (CommonRepository repository : this.repository.getOrderedRepositories()) { - if (repository.isRoot()) { - if (insertOrUpdate.isNotIgnoreRoot()) { - if (repository.matches(context) || insertOrUpdate.isIncludeRoot()) { - totalCount += repository.execute(context, insertOrUpdate); - } - } - } else { - boolean isMatch = repository.matches(context); - boolean isAggregated = repository.isAggregated(); - if (!isMatch && !isAggregated) { - continue; - } - List rootEntities = insertOrUpdate.getEntities(); - for (Object rootEntity : rootEntities) { - EntityElement entityElement = repository.getEntityElement(); - Object targetEntity = entityElement.getValue(rootEntity); - if (targetEntity == null) { - continue; - } - List entities = CollectionUtils.toList(targetEntity); - if (entities.isEmpty()) { - continue; - } - if (isMatch) { - repository.getBoundValue(context, rootEntity, entities); - } - OperationFactory operationFactory = repository.getOperationFactory(); - Operation operation = operationFactory.buildInsertOrUpdate(entities); - operation.switchRoot(isMatch); - totalCount += repository.execute(context, operation); - if (entities.size() == 1) { - repository.setBoundId(context, rootEntity, entities.get(0)); - } - } - } - } - return totalCount; + @Override + public long handle(Context context, EntityOp entityOp) { + return entityOpHandler.handle(context, entityOp); } } diff --git a/dorive-api/src/main/java/com/gitee/dorive/api/entity/event/def/ListenerDef.java b/dorive-core/src/main/java/com/gitee/dorive/core/impl/handler/AdaptiveEntityHandler.java similarity index 41% rename from dorive-api/src/main/java/com/gitee/dorive/api/entity/event/def/ListenerDef.java rename to dorive-core/src/main/java/com/gitee/dorive/core/impl/handler/AdaptiveEntityHandler.java index 5a3f6130fb414979318afd9144e10b80c437a8d3..5c4b8783cf5b6e7a03de6258b4cda49e3ca95f91 100644 --- a/dorive-api/src/main/java/com/gitee/dorive/api/entity/event/def/ListenerDef.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/impl/handler/AdaptiveEntityHandler.java @@ -15,39 +15,44 @@ * limitations under the License. */ -package com.gitee.dorive.api.entity.event.def; +package com.gitee.dorive.core.impl.handler; -import com.gitee.dorive.api.annotation.event.Listener; +import com.gitee.dorive.core.api.context.Context; +import com.gitee.dorive.core.api.executor.EntityHandler; +import com.gitee.dorive.core.entity.enums.JoinType; +import com.gitee.dorive.core.impl.handler.joiner.MultiEntityHandler; +import com.gitee.dorive.core.impl.handler.joiner.SingleEntityHandler; +import com.gitee.dorive.core.impl.handler.joiner.UnionEntityHandler; +import com.gitee.dorive.core.repository.CommonRepository; import lombok.AllArgsConstructor; import lombok.Data; -import lombok.NoArgsConstructor; -import org.springframework.core.annotation.AnnotatedElementUtils; -import java.lang.reflect.AnnotatedElement; +import java.util.List; @Data -@NoArgsConstructor @AllArgsConstructor -public class ListenerDef { - private String[] publishers; - private Class entityClass; - private String[] events; - private boolean onlyRoot; - private boolean afterCommit; - private Class[] throwExceptions; - - public static ListenerDef fromElement(AnnotatedElement element) { - Listener listener = AnnotatedElementUtils.getMergedAnnotation(element, Listener.class); - if (listener != null) { - ListenerDef listenerDef = new ListenerDef(); - listenerDef.setPublishers(listener.publishers()); - listenerDef.setEntityClass(listener.entityClass()); - listenerDef.setEvents(listener.events()); - listenerDef.setOnlyRoot(listener.onlyRoot()); - listenerDef.setAfterCommit(listener.afterCommit()); - listenerDef.setThrowExceptions(listener.throwExceptions()); - return listenerDef; +public class AdaptiveEntityHandler implements EntityHandler { + + private CommonRepository repository; + + @Override + public long handle(Context context, List entities) { + EntityHandler entityHandler = newEntityHandler(entities); + return entityHandler != null ? entityHandler.handle(context, entities) : 0L; + } + + private EntityHandler newEntityHandler(List entities) { + JoinType joinType = repository.getJoinType(); + if (joinType == JoinType.SINGLE) { + return new SingleEntityHandler(entities, repository); + + } else if (joinType == JoinType.MULTI) { + return new MultiEntityHandler(entities, repository); + + } else if (joinType == JoinType.UNION) { + return new UnionEntityHandler(entities, repository); } 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 cbf33aa9c331b0e696fd7e38f23b2a55b1e74fca..a0499b3b97aa658bff7eb4be845595611f709886 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 @@ -19,96 +19,40 @@ package com.gitee.dorive.core.impl.handler; import com.gitee.dorive.core.api.context.Context; import com.gitee.dorive.core.api.executor.EntityHandler; -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.cop.Query; -import com.gitee.dorive.core.entity.enums.JoinType; -import com.gitee.dorive.core.impl.binder.ValueRouteBinder; -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.impl.resolver.BinderResolver; import com.gitee.dorive.core.repository.AbstractContextRepository; import com.gitee.dorive.core.repository.CommonRepository; -import lombok.AllArgsConstructor; import lombok.Data; import java.util.ArrayList; import java.util.List; @Data -@AllArgsConstructor public class BatchEntityHandler implements EntityHandler { private final AbstractContextRepository repository; + private final List entityHandlers; + + public BatchEntityHandler(AbstractContextRepository repository) { + this.repository = repository; + List subRepositories = repository.getSubRepositories(); + this.entityHandlers = new ArrayList<>(subRepositories.size()); + for (CommonRepository subRepository : subRepositories) { + EntityHandler entityHandler = new AdaptiveEntityHandler(subRepository); + if (subRepository.hasValueRouteBinders()) { + entityHandler = new ValueFilterEntityHandler(subRepository, entityHandler); + } + entityHandler = new ContextMatchEntityHandler(subRepository, entityHandler); + entityHandlers.add(entityHandler); + } + } @Override public long handle(Context context, List entities) { long totalCount = 0L; - for (CommonRepository repository : this.repository.getSubRepositories()) { - if (repository.matches(context)) { - List newEntities = filterByValueRouteBinders(context, entities, repository); - if (newEntities.isEmpty()) { - continue; - } - EntityJoiner entityJoiner = newEntityJoiner(repository, newEntities.size()); - if (entityJoiner == null) { - continue; - } - Example example = entityJoiner.newExample(context, newEntities); - if (example.isEmpty()) { - continue; - } - OperationFactory operationFactory = repository.getOperationFactory(); - Query query = operationFactory.buildQueryByExample(example); - query.includeRoot(); - Result result = repository.executeQuery(context, query); - entityJoiner.join(context, newEntities, result); - totalCount += result.getCount(); - } + for (EntityHandler entityHandler : entityHandlers) { + totalCount += entityHandler.handle(context, entities); } return totalCount; } - private List filterByValueRouteBinders(Context context, List entities, CommonRepository repository) { - BinderResolver binderResolver = repository.getBinderResolver(); - List valueRouteBinders = binderResolver.getValueRouteBinders(); - if (valueRouteBinders.isEmpty()) { - return entities; - } - List newEntities = new ArrayList<>(entities.size()); - for (Object entity : entities) { - boolean isValueEqual = true; - for (ValueRouteBinder valueRouteBinder : valueRouteBinders) { - Object fieldValue = valueRouteBinder.getFieldValue(context, null); - Object boundValue = valueRouteBinder.getBoundValue(context, entity); - boundValue = valueRouteBinder.input(context, boundValue); - if (!fieldValue.equals(boundValue)) { - isValueEqual = false; - break; - } - } - if (isValueEqual) { - newEntities.add(entity); - } - } - return newEntities; - } - - 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-api/src/main/java/com/gitee/dorive/api/annotation/query/EnableQuery.java b/dorive-core/src/main/java/com/gitee/dorive/core/impl/handler/ContextMatchEntityHandler.java similarity index 55% rename from dorive-api/src/main/java/com/gitee/dorive/api/annotation/query/EnableQuery.java rename to dorive-core/src/main/java/com/gitee/dorive/core/impl/handler/ContextMatchEntityHandler.java index 82426320f822b74f8b122a2d1ac426994e53c746..691830733265fce9a972f09830df09121cf7d9b6 100644 --- a/dorive-api/src/main/java/com/gitee/dorive/api/annotation/query/EnableQuery.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/impl/handler/ContextMatchEntityHandler.java @@ -15,21 +15,26 @@ * limitations under the License. */ -package com.gitee.dorive.api.annotation.query; +package com.gitee.dorive.core.impl.handler; -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 com.gitee.dorive.core.api.context.Context; +import com.gitee.dorive.core.api.executor.EntityHandler; +import com.gitee.dorive.core.repository.CommonRepository; +import lombok.AllArgsConstructor; +import lombok.Data; -@Inherited -@Documented -@Target(ElementType.TYPE) -@Retention(RetentionPolicy.RUNTIME) -public @interface EnableQuery { +import java.util.List; - Class[] queries(); +@Data +@AllArgsConstructor +public class ContextMatchEntityHandler implements EntityHandler { + + private CommonRepository repository; + private EntityHandler entityHandler; + + @Override + public long handle(Context context, List entities) { + return repository.matches(context) ? entityHandler.handle(context, entities) : 0L; + } } diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/impl/handler/DelegatedEntityHandler.java b/dorive-core/src/main/java/com/gitee/dorive/core/impl/handler/DelegatedEntityHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..15cecd5da896d8e4515d2be229cb92733e46707e --- /dev/null +++ b/dorive-core/src/main/java/com/gitee/dorive/core/impl/handler/DelegatedEntityHandler.java @@ -0,0 +1,62 @@ +/* + * 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.core.api.context.Context; +import com.gitee.dorive.core.api.executor.EntityHandler; +import com.gitee.dorive.core.repository.AbstractContextRepository; +import lombok.AllArgsConstructor; +import lombok.Data; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Data +@AllArgsConstructor +public class DelegatedEntityHandler implements EntityHandler { + + private final AbstractContextRepository repository; + private final Map, EntityHandler> entityHandlerMap; + + @Override + public long handle(Context context, List entities) { + int size = entityHandlerMap.size(); + Map, List> subEntitiesMap = new HashMap<>(size * 4 / 3 + 1); + for (Object entity : entities) { + Class entityType = entity.getClass(); + List subEntities = subEntitiesMap.computeIfAbsent(entityType, k -> new ArrayList<>()); + subEntities.add(entity); + } + long totalCount = 0L; + for (Map.Entry, List> entry : subEntitiesMap.entrySet()) { + Class entityType = entry.getKey(); + List subEntities = entry.getValue(); + EntityHandler entityHandler = entityHandlerMap.get(entityType); + if (entityHandler == null) { + entityHandler = entityHandlerMap.get(repository.getEntityClass()); + } + if (entityHandler != null) { + totalCount += entityHandler.handle(context, subEntities); + } + } + return totalCount; + } + +} diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/impl/handler/ValueFilterEntityHandler.java b/dorive-core/src/main/java/com/gitee/dorive/core/impl/handler/ValueFilterEntityHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..66d8df0078b1e1db22e64777679a57402633442a --- /dev/null +++ b/dorive-core/src/main/java/com/gitee/dorive/core/impl/handler/ValueFilterEntityHandler.java @@ -0,0 +1,69 @@ +/* + * 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.core.api.context.Context; +import com.gitee.dorive.core.api.executor.EntityHandler; +import com.gitee.dorive.core.impl.binder.ValueRouteBinder; +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.List; + +@Data +@AllArgsConstructor +public class ValueFilterEntityHandler implements EntityHandler { + + private CommonRepository repository; + private EntityHandler entityHandler; + + @Override + public long handle(Context context, List entities) { + List subEntities = filterByValueRouteBinders(context, entities); + return !subEntities.isEmpty() ? entityHandler.handle(context, subEntities) : 0L; + } + + private List filterByValueRouteBinders(Context context, List entities) { + BinderResolver binderResolver = repository.getBinderResolver(); + List valueRouteBinders = binderResolver.getValueRouteBinders(); + if (valueRouteBinders.isEmpty()) { + return entities; + } + List subEntities = new ArrayList<>(entities.size()); + for (Object entity : entities) { + boolean isValueEqual = true; + for (ValueRouteBinder valueRouteBinder : valueRouteBinders) { + Object fieldValue = valueRouteBinder.getFieldValue(context, null); + Object boundValue = valueRouteBinder.getBoundValue(context, entity); + boundValue = valueRouteBinder.input(context, boundValue); + if (!fieldValue.equals(boundValue)) { + isValueEqual = false; + break; + } + } + if (isValueEqual) { + subEntities.add(entity); + } + } + return subEntities; + } + +} diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/impl/handler/eo/BatchEntityOpHandler.java b/dorive-core/src/main/java/com/gitee/dorive/core/impl/handler/eo/BatchEntityOpHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..f611f9a549113844fed7d14421964a44e17c3a6c --- /dev/null +++ b/dorive-core/src/main/java/com/gitee/dorive/core/impl/handler/eo/BatchEntityOpHandler.java @@ -0,0 +1,171 @@ +/* + * 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.eo; + +import com.gitee.dorive.api.entity.core.EntityElement; +import com.gitee.dorive.core.api.context.Context; +import com.gitee.dorive.core.api.executor.EntityOpHandler; +import com.gitee.dorive.core.entity.operation.EntityOp; +import com.gitee.dorive.core.entity.operation.Operation; +import com.gitee.dorive.core.entity.operation.eop.Delete; +import com.gitee.dorive.core.entity.operation.eop.Insert; +import com.gitee.dorive.core.entity.operation.eop.InsertOrUpdate; +import com.gitee.dorive.core.entity.operation.eop.Update; +import com.gitee.dorive.core.impl.factory.OperationFactory; +import com.gitee.dorive.core.repository.AbstractContextRepository; +import com.gitee.dorive.core.repository.CommonRepository; +import com.gitee.dorive.core.util.CollectionUtils; +import lombok.AllArgsConstructor; +import lombok.Data; + +import java.util.List; + +@Data +@AllArgsConstructor +public class BatchEntityOpHandler implements EntityOpHandler { + + private final AbstractContextRepository repository; + + @Override + public long handle(Context context, EntityOp entityOp) { + int totalCount = 0; + if (entityOp instanceof Insert) { + totalCount += executeInsert(context, entityOp); + + } else if (entityOp instanceof Update) { + totalCount += executeUpdateOrDelete(context, entityOp); + + } else if (entityOp instanceof Delete) { + totalCount += executeUpdateOrDelete(context, entityOp); + + } else if (entityOp instanceof InsertOrUpdate) { + totalCount += executeInsertOrUpdate(context, entityOp); + } + return totalCount; + } + + private int executeInsert(Context context, EntityOp entityOp) { + int totalCount = 0; + for (CommonRepository repository : this.repository.getOrderedRepositories()) { + boolean isRoot = repository.isRoot(); + if (isRoot) { + totalCount += executeRoot(repository, context, entityOp); + continue; + } + boolean isMatch = repository.matches(context); + boolean isAggregated = repository.isAggregated(); + if (!isMatch && !isAggregated) continue; + + List rootEntities = entityOp.getEntities(); + for (Object rootEntity : rootEntities) { + List entities = getEntities(repository, rootEntity); + if (entities == null) continue; + + if (isMatch) { + repository.getBoundValue(context, rootEntity, entities); + } + Operation operation = new Insert(entities); + operation.switchRoot(isMatch); + totalCount += repository.execute(context, operation); + if (entities.size() == 1) { + repository.setBoundId(context, rootEntity, entities.get(0)); + } + } + } + return totalCount; + } + + private int executeUpdateOrDelete(Context context, EntityOp entityOp) { + int totalCount = 0; + for (CommonRepository repository : this.repository.getOrderedRepositories()) { + boolean isRoot = repository.isRoot(); + if (isRoot) { + totalCount += executeRoot(repository, context, entityOp); + continue; + } + boolean isMatch = repository.matches(context); + boolean isAggregated = repository.isAggregated(); + if (!isMatch && !isAggregated) continue; + + List rootEntities = entityOp.getEntities(); + for (Object rootEntity : rootEntities) { + List entities = getEntities(repository, rootEntity); + if (entities == null) continue; + + Operation operation = entityOp instanceof Update ? new Update(entities) : new Delete(entities); + operation.switchRoot(isMatch); + totalCount += repository.execute(context, operation); + } + } + return totalCount; + } + + private int executeInsertOrUpdate(Context context, EntityOp entityOp) { + int totalCount = 0; + for (CommonRepository repository : this.repository.getOrderedRepositories()) { + boolean isRoot = repository.isRoot(); + if (isRoot) { + totalCount += executeRoot(repository, context, entityOp); + continue; + } + boolean isMatch = repository.matches(context); + boolean isAggregated = repository.isAggregated(); + if (!isMatch && !isAggregated) continue; + + List rootEntities = entityOp.getEntities(); + for (Object rootEntity : rootEntities) { + List entities = getEntities(repository, rootEntity); + if (entities == null) continue; + + if (isMatch) { + repository.getBoundValue(context, rootEntity, entities); + } + OperationFactory operationFactory = repository.getOperationFactory(); + Operation operation = operationFactory.buildInsertOrUpdate(entities); + operation.switchRoot(isMatch); + totalCount += repository.execute(context, operation); + if (entities.size() == 1) { + repository.setBoundId(context, rootEntity, entities.get(0)); + } + } + } + return totalCount; + } + + private int executeRoot(CommonRepository repository, Context context, EntityOp entityOp) { + if (entityOp.isNotIgnoreRoot()) { + if (repository.matches(context) || entityOp.isIncludeRoot()) { + return repository.execute(context, entityOp); + } + } + return 0; + } + + private List getEntities(CommonRepository repository, Object rootEntity) { + EntityElement entityElement = repository.getEntityElement(); + Object targetEntity = entityElement.getValue(rootEntity); + if (targetEntity != null) { + List entities = CollectionUtils.toList(targetEntity); + if (!entities.isEmpty()) { + return entities; + } + } + return null; + } + +} diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/impl/handler/eo/DelegatedEntityOpHandler.java b/dorive-core/src/main/java/com/gitee/dorive/core/impl/handler/eo/DelegatedEntityOpHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..3ce12301659988fe25e5a14cbb9fe15868db1cc0 --- /dev/null +++ b/dorive-core/src/main/java/com/gitee/dorive/core/impl/handler/eo/DelegatedEntityOpHandler.java @@ -0,0 +1,86 @@ +/* + * 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.eo; + +import com.gitee.dorive.core.api.context.Context; +import com.gitee.dorive.core.api.executor.EntityOpHandler; +import com.gitee.dorive.core.entity.operation.EntityOp; +import com.gitee.dorive.core.entity.operation.eop.Delete; +import com.gitee.dorive.core.entity.operation.eop.Insert; +import com.gitee.dorive.core.entity.operation.eop.InsertOrUpdate; +import com.gitee.dorive.core.entity.operation.eop.Update; +import com.gitee.dorive.core.impl.factory.OperationFactory; +import com.gitee.dorive.core.repository.AbstractContextRepository; +import lombok.AllArgsConstructor; +import lombok.Data; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Data +@AllArgsConstructor +public class DelegatedEntityOpHandler implements EntityOpHandler { + + private final AbstractContextRepository repository; + private final Map, EntityOpHandler> entityOpHandlerMap; + + @Override + public long handle(Context context, EntityOp entityOp) { + List entities = entityOp.getEntities(); + int size = entityOpHandlerMap.size(); + Map, List> subEntitiesMap = new HashMap<>(size * 4 / 3 + 1); + for (Object entity : entities) { + Class entityType = entity.getClass(); + List subEntities = subEntitiesMap.computeIfAbsent(entityType, k -> new ArrayList<>()); + subEntities.add(entity); + } + long totalCount = 0L; + for (Map.Entry, List> entry : subEntitiesMap.entrySet()) { + Class entityType = entry.getKey(); + List subEntities = entry.getValue(); + EntityOpHandler entityOpHandler = entityOpHandlerMap.get(entityType); + if (entityOpHandler == null) { + entityOpHandler = entityOpHandlerMap.get(repository.getEntityClass()); + } + if (entityOpHandler != null) { + totalCount += entityOpHandler.handle(context, buildOperation(entityOp, subEntities)); + } + } + return totalCount; + } + + private EntityOp buildOperation(EntityOp entityOp, List entities) { + if (entityOp instanceof Insert) { + return new Insert(entities); + + } else if (entityOp instanceof Update) { + return new Update(entities); + + } else if (entityOp instanceof Delete) { + return new Delete(entities); + + } else if (entityOp instanceof InsertOrUpdate) { + OperationFactory operationFactory = repository.getOperationFactory(); + return operationFactory.buildInsertOrUpdate(entities); + } + return null; + } + +} 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/handler/joiner/AbstractEntityJoiner.java similarity index 36% rename from dorive-core/src/main/java/com/gitee/dorive/core/impl/joiner/AbstractEntityJoiner.java rename to dorive-core/src/main/java/com/gitee/dorive/core/impl/handler/joiner/AbstractEntityJoiner.java index 381c789f8d71a2a7e3ace6a6c386890537d890ee..0d5d662291054e700739d51d05e3be1e3695c6ca 100644 --- 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/handler/joiner/AbstractEntityJoiner.java @@ -15,101 +15,67 @@ * limitations under the License. */ -package com.gitee.dorive.core.impl.joiner; +package com.gitee.dorive.core.impl.handler.joiner; import com.gitee.dorive.api.entity.core.EntityElement; import com.gitee.dorive.core.api.context.Context; -import com.gitee.dorive.core.api.executor.EntityJoiner; +import com.gitee.dorive.core.api.executor.EntityHandler; import com.gitee.dorive.core.entity.executor.Example; import com.gitee.dorive.core.entity.executor.Result; +import com.gitee.dorive.core.entity.operation.cop.Query; import com.gitee.dorive.core.impl.binder.WeakBinder; +import com.gitee.dorive.core.impl.factory.OperationFactory; import com.gitee.dorive.core.impl.resolver.BinderResolver; import com.gitee.dorive.core.repository.CommonRepository; -import org.apache.commons.lang3.StringUtils; +import lombok.Getter; +import lombok.Setter; -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 { +@Getter +@Setter +public abstract class AbstractEntityJoiner extends ObjectsJoiner implements EntityHandler { protected CommonRepository repository; - protected Map rootIndex; - protected Set keys; - protected Map recordIndex; - protected int averageSize; - public AbstractEntityJoiner(CommonRepository repository, int entitiesSize) { + public AbstractEntityJoiner(List entities, CommonRepository repository) { + super(entities, repository.isCollection()); 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 appendFilterCriteria(Context context, Example example) { - if (example == null || example.isEmpty()) { - return; - } - BinderResolver binderResolver = repository.getBinderResolver(); - List weakBinders = binderResolver.getWeakBinders(); - for (WeakBinder weakBinder : weakBinders) { - Object boundValue = weakBinder.input(context, null); - if (boundValue != null) { - String fieldName = weakBinder.getFieldName(); - example.eq(fieldName, boundValue); - } - } - binderResolver.appendFilterValue(context, example); - } - - 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); + public long handle(Context context, List entities) { + Example example = newExample(context, entities); + if (!example.isEmpty()) { + OperationFactory operationFactory = repository.getOperationFactory(); + Query query = operationFactory.buildQueryByExample(example); + query.includeRoot(); + Result result = repository.executeQuery(context, query); + setAverageSize(result.getRecords().size() / entities.size() + 1); + handleResult(context, result); + join(); + return result.getCount(); } + return 0L; } - 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 appendFilterCriteria(Context context, Example example) { + if (example != null && !example.isEmpty()) { + BinderResolver binderResolver = repository.getBinderResolver(); + List weakBinders = binderResolver.getWeakBinders(); + for (WeakBinder weakBinder : weakBinders) { + Object boundValue = weakBinder.input(context, null); + if (boundValue != null) { + String fieldName = weakBinder.getFieldName(); + example.eq(fieldName, boundValue); + } } + binderResolver.appendFilterValue(context, example); } } - protected void joinOne(Object entity, Object object) { - if (entity == null || object == null) { - return; - } + @Override + protected void doJoin(Object entity, Object object) { EntityElement entityElement = repository.getEntityElement(); Object value = entityElement.getValue(entity); if (value == null) { @@ -117,6 +83,8 @@ public abstract class AbstractEntityJoiner implements EntityJoiner { } } - protected abstract void buildRecordIndex(Context context, List entities, Result result); + protected abstract Example newExample(Context context, List entities); + + protected abstract void handleResult(Context context, 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/handler/joiner/MultiEntityHandler.java similarity index 89% rename from dorive-core/src/main/java/com/gitee/dorive/core/impl/joiner/MultiEntityJoiner.java rename to dorive-core/src/main/java/com/gitee/dorive/core/impl/handler/joiner/MultiEntityHandler.java index 7cf14a8831430421dedfe62d36415b6c2ee01bbc..8871eafc72e3e9203ae38adc6af79058c99915ad 100644 --- 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/handler/joiner/MultiEntityHandler.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package com.gitee.dorive.core.impl.joiner; +package com.gitee.dorive.core.impl.handler.joiner; import com.gitee.dorive.core.api.context.Context; import com.gitee.dorive.core.entity.executor.Example; @@ -33,12 +33,12 @@ import java.util.stream.Collectors; @Getter @Setter -public class MultiEntityJoiner extends AbstractEntityJoiner { +public class MultiEntityHandler extends AbstractEntityJoiner { private List binders; - public MultiEntityJoiner(CommonRepository repository, int entitiesSize) { - super(repository, entitiesSize); + public MultiEntityHandler(List entities, CommonRepository repository) { + super(entities, repository); this.binders = repository.getRootStrongBinders(); } @@ -75,10 +75,10 @@ public class MultiEntityJoiner extends AbstractEntityJoiner { if (keyBuilder != null && keyBuilder.length() > 0) { keyBuilder.deleteCharAt(keyBuilder.length() - 1); String key = keyBuilder.toString(); - if (keys.contains(key)) { + if (containsKey(key)) { multiInBuilder.clearLast(); } - addToRootIndex(entity, key); + addLeft(entity, key); } } @@ -86,7 +86,7 @@ public class MultiEntityJoiner extends AbstractEntityJoiner { } @Override - protected void buildRecordIndex(Context context, List entities, Result result) { + protected void handleResult(Context context, Result result) { List records = result.getRecords(); for (Object entity : records) { StringBuilder keyBuilder = new StringBuilder(); @@ -103,7 +103,7 @@ public class MultiEntityJoiner extends AbstractEntityJoiner { if (keyBuilder != null && keyBuilder.length() > 0) { keyBuilder.deleteCharAt(keyBuilder.length() - 1); String key = keyBuilder.toString(); - addToRecordIndex(key, entity); + addRight(key, entity); } } } diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/impl/handler/joiner/ObjectsJoiner.java b/dorive-core/src/main/java/com/gitee/dorive/core/impl/handler/joiner/ObjectsJoiner.java new file mode 100644 index 0000000000000000000000000000000000000000..d2e2d0b28c58808138839963efe11e151339990b --- /dev/null +++ b/dorive-core/src/main/java/com/gitee/dorive/core/impl/handler/joiner/ObjectsJoiner.java @@ -0,0 +1,96 @@ +/* + * 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.joiner; + +import lombok.Data; +import org.apache.commons.lang3.StringUtils; + +import java.util.*; + +@Data +public abstract class ObjectsJoiner { + private List entities; + private int initialCapacity; + private Map hashCodeKeyMap; + private Set keys; + private Map keyObjectMap; + private boolean collection; + private int averageSize; + + public ObjectsJoiner(List entities, boolean collection) { + this.entities = entities; + this.initialCapacity = entities.size() * 4 / 3 + 1; + this.hashCodeKeyMap = new HashMap<>(initialCapacity); + this.keys = new HashSet<>(initialCapacity); + this.keyObjectMap = new HashMap<>(initialCapacity); + this.collection = collection; + this.averageSize = 10; + } + + public void addLeft(Object entity, String key) { + if (entity != null && StringUtils.isNotBlank(key)) { + hashCodeKeyMap.put(System.identityHashCode(entity), key); + keys.add(key); + } + } + + @SuppressWarnings("unchecked") + public void addRight(String key, Object entity) { + if (StringUtils.isNotBlank(key) && entity != null) { + if (collection) { + Collection collection = (Collection) keyObjectMap.computeIfAbsent(key, k -> new ArrayList<>(averageSize)); + collection.add(entity); + } else { + keyObjectMap.putIfAbsent(key, entity); + } + } + } + + public String getLeftKey(Object entity) { + return entity != null ? hashCodeKeyMap.get(System.identityHashCode(entity)) : null; + } + + public boolean containsKey(String key) { + return keys.contains(key); + } + + public Object getRight(String key) { + return key != null ? keyObjectMap.get(key) : null; + } + + public boolean isEmpty() { + return hashCodeKeyMap == null || hashCodeKeyMap.isEmpty() || keyObjectMap == null || keyObjectMap.isEmpty(); + } + + public void join() { + if (!isEmpty()) { + for (Object entity : entities) { + String key = getLeftKey(entity); + if (key != null) { + Object object = getRight(key); + if (entity != null || object != null) { + doJoin(entity, object); + } + } + } + } + } + + protected abstract void doJoin(Object entity, Object object); + +} diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/impl/joiner/SingleEntityJoiner.java b/dorive-core/src/main/java/com/gitee/dorive/core/impl/handler/joiner/SingleEntityHandler.java similarity index 85% rename from dorive-core/src/main/java/com/gitee/dorive/core/impl/joiner/SingleEntityJoiner.java rename to dorive-core/src/main/java/com/gitee/dorive/core/impl/handler/joiner/SingleEntityHandler.java index 0ff9f60631900392fda1f755ebc6b17ce93150d0..e6a80c8fa558298cace0a694ca01b9f69738d2f2 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/impl/joiner/SingleEntityJoiner.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/impl/handler/joiner/SingleEntityHandler.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package com.gitee.dorive.core.impl.joiner; +package com.gitee.dorive.core.impl.handler.joiner; import com.gitee.dorive.core.api.context.Context; import com.gitee.dorive.core.entity.executor.Example; @@ -31,12 +31,12 @@ import java.util.List; @Getter @Setter -public class SingleEntityJoiner extends AbstractEntityJoiner { +public class SingleEntityHandler extends AbstractEntityJoiner { private StrongBinder binder; - public SingleEntityJoiner(CommonRepository repository, int entitiesSize) { - super(repository, entitiesSize); + public SingleEntityHandler(List entities, CommonRepository repository) { + super(entities, repository); this.binder = repository.getRootStrongBinders().get(0); } @@ -63,23 +63,23 @@ public class SingleEntityJoiner extends AbstractEntityJoiner { boundValue = binder.input(context, boundValue); if (boundValue != null) { String key = boundValue.toString(); - if (!keys.contains(key)) { + if (!containsKey(key)) { boundValues.add(boundValue); } - addToRootIndex(entity, key); + addLeft(entity, key); } } return boundValues; } @Override - protected void buildRecordIndex(Context context, List entities, Result result) { + protected void handleResult(Context context, 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); + addRight(key, entity); } } } diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/impl/joiner/UnionEntityJoiner.java b/dorive-core/src/main/java/com/gitee/dorive/core/impl/handler/joiner/UnionEntityHandler.java similarity index 87% rename from dorive-core/src/main/java/com/gitee/dorive/core/impl/joiner/UnionEntityJoiner.java rename to dorive-core/src/main/java/com/gitee/dorive/core/impl/handler/joiner/UnionEntityHandler.java index 31662a6fe77bca45ebc7bf4f5406fb0b3ec39b88..2cfbade370b8c3aa22e53819e3e9c7ab6c0056b3 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/impl/joiner/UnionEntityJoiner.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/impl/handler/joiner/UnionEntityHandler.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package com.gitee.dorive.core.impl.joiner; +package com.gitee.dorive.core.impl.handler.joiner; import com.gitee.dorive.core.api.context.Context; import com.gitee.dorive.core.entity.executor.Example; @@ -33,10 +33,10 @@ import java.util.Map; @Getter @Setter -public class UnionEntityJoiner extends AbstractEntityJoiner { +public class UnionEntityHandler extends AbstractEntityJoiner { - public UnionEntityJoiner(CommonRepository repository, int entitiesSize) { - super(repository, entitiesSize); + public UnionEntityHandler(List entities, CommonRepository repository) { + super(entities, repository); } @Override @@ -51,7 +51,7 @@ public class UnionEntityJoiner extends AbstractEntityJoiner { String row = Integer.toString(index + 1); example.setSelectSuffix(row + " as $row"); unionExample.addExample(example); - addToRootIndex(entity, row); + addLeft(entity, row); } return unionExample; } @@ -81,7 +81,7 @@ public class UnionEntityJoiner extends AbstractEntityJoiner { @Override @SuppressWarnings("unchecked") - protected void buildRecordIndex(Context context, List entities, Result result) { + protected void handleResult(Context context, Result result) { List> recordMaps = result.getRecordMaps(); for (Map resultMap : recordMaps) { Object row = resultMap.get("$row"); @@ -90,10 +90,10 @@ public class UnionEntityJoiner extends AbstractEntityJoiner { if (entity != null) { if (rows != null) { for (String eachRow : rows) { - addToRecordIndex(eachRow, entity); + addRight(eachRow, entity); } } else if (row != null) { - addToRecordIndex(row.toString(), entity); + addRight(row.toString(), entity); } } } diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/impl/processor/SpELProcessor.java b/dorive-core/src/main/java/com/gitee/dorive/core/impl/processor/SpELProcessor.java index d2d75b6851162ec1f6179e9e72c0f581edf3c7ff..f1b8bf31cee3aeb85af2768438332495d3344399 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/impl/processor/SpELProcessor.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/impl/processor/SpELProcessor.java @@ -38,7 +38,7 @@ public class SpELProcessor implements Processor { @Override public Object input(Context context, Object value) { EvaluationContext evaluationContext = new StandardEvaluationContext(); - evaluationContext.setVariable("ctx", context); + evaluationContext.setVariable("ctx", context.getAttachments()); evaluationContext.setVariable("val", value); return expression.getValue(evaluationContext); } 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/DerivedRepositoryResolver.java similarity index 52% rename from dorive-core/src/main/java/com/gitee/dorive/core/impl/resolver/DerivedResolver.java rename to dorive-core/src/main/java/com/gitee/dorive/core/impl/resolver/DerivedRepositoryResolver.java index 76432c751c387ccb220ce2cee6051fd5a2bd1b02..e4d5c214bf63ce620aef4d4c2671ba6f913af73e 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/DerivedRepositoryResolver.java @@ -17,63 +17,72 @@ package com.gitee.dorive.core.impl.resolver; -import cn.hutool.core.lang.Pair; +import com.gitee.dorive.api.entity.core.def.RepositoryDef; +import com.gitee.dorive.core.api.executor.EntityHandler; +import com.gitee.dorive.core.api.executor.EntityOpHandler; +import com.gitee.dorive.core.api.executor.Executor; import com.gitee.dorive.core.repository.AbstractContextRepository; import lombok.Data; import org.springframework.context.ApplicationContext; -import org.springframework.util.ReflectionUtils; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; import java.util.LinkedHashMap; -import java.util.List; import java.util.Map; @Data -public class DerivedResolver { +public class DerivedRepositoryResolver { private AbstractContextRepository repository; - private Map, AbstractContextRepository> classRepositoryMap = new LinkedHashMap<>(3 * 4 / 3 + 1); + private Map, AbstractContextRepository> classRepositoryMap; - public DerivedResolver(AbstractContextRepository repository) { + public DerivedRepositoryResolver(AbstractContextRepository repository) { this.repository = repository; - resolve(); } - private void resolve() { - ReflectionUtils.doWithLocalFields(repository.getClass(), declaredField -> { - Class fieldClass = declaredField.getType(); - if (AbstractContextRepository.class.isAssignableFrom(fieldClass)) { + public void resolve() { + RepositoryDef repositoryDef = repository.getRepositoryDef(); + Class[] derived = repositoryDef.getDerived(); + classRepositoryMap = new LinkedHashMap<>(derived.length * 4 / 3 + 1); + for (Class clazz : derived) { + if (AbstractContextRepository.class.isAssignableFrom(clazz)) { ApplicationContext applicationContext = repository.getApplicationContext(); - Object beanInstance = applicationContext.getBean(fieldClass); + Object beanInstance = applicationContext.getBean(clazz); AbstractContextRepository abstractContextRepository = (AbstractContextRepository) beanInstance; Class fieldEntityClass = abstractContextRepository.getEntityClass(); if (repository.getEntityClass().isAssignableFrom(fieldEntityClass)) { classRepositoryMap.put(fieldEntityClass, abstractContextRepository); } } - }); + } } public boolean hasDerived() { return !classRepositoryMap.isEmpty(); } - public Collection, List>> distribute(List entities) { + public Map, EntityHandler> getEntityHandlerMap(EntityHandler entityHandler) { int size = classRepositoryMap.size() + 1; - Map, Pair, List>> classRepoEntitiesPairMap = new HashMap<>(size * 4 / 3 + 1); - for (Object entity : entities) { - Class clazz = entity.getClass(); - Pair, List> repoEntitiesPair = classRepoEntitiesPairMap.computeIfAbsent(clazz, key -> { - AbstractContextRepository repository = classRepositoryMap.getOrDefault(key, this.repository); - List partEntities = new ArrayList<>(entities.size()); - return new Pair<>(repository, partEntities); - }); - List partEntities = repoEntitiesPair.getValue(); - partEntities.add(entity); - } - return classRepoEntitiesPairMap.values(); + Map, EntityHandler> entityHandlerMap = new LinkedHashMap<>(size * 4 / 3 + 1); + entityHandlerMap.put(repository.getEntityClass(), entityHandler); + classRepositoryMap.forEach((clazz, repository) -> { + Executor executor = repository.getExecutor(); + if (executor instanceof EntityHandler) { + entityHandlerMap.put(clazz, (EntityHandler) executor); + } + }); + return entityHandlerMap; + } + + public Map, EntityOpHandler> getEntityOpHandlerMap(EntityOpHandler entityOpHandler) { + int size = classRepositoryMap.size() + 1; + Map, EntityOpHandler> entityOpHandlerMap = new LinkedHashMap<>(size * 4 / 3 + 1); + entityOpHandlerMap.put(repository.getEntityClass(), entityOpHandler); + classRepositoryMap.forEach((clazz, repository) -> { + Executor executor = repository.getExecutor(); + if (executor instanceof EntityOpHandler) { + entityOpHandlerMap.put(clazz, (EntityOpHandler) executor); + } + }); + return entityOpHandlerMap; } } 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 35cf21285f178246e2c2347657f2f11861131914..9b3467c2655cbf6372daa11d68f03ce9e1887a01 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 @@ -24,10 +24,12 @@ import com.gitee.dorive.api.entity.core.EntityDefinition; import com.gitee.dorive.api.entity.core.def.EntityDef; import com.gitee.dorive.api.entity.core.def.OrderDef; import com.gitee.dorive.api.entity.core.EntityElement; +import com.gitee.dorive.api.entity.core.def.RepositoryDef; import com.gitee.dorive.api.impl.core.EntityDefinitionResolver; import com.gitee.dorive.api.impl.core.EntityElementResolver; import com.gitee.dorive.api.util.ReflectUtils; import com.gitee.dorive.core.api.executor.EntityHandler; +import com.gitee.dorive.core.api.executor.EntityOpHandler; import com.gitee.dorive.core.api.executor.Executor; import com.gitee.dorive.core.api.factory.EntityFactory; import com.gitee.dorive.core.api.factory.EntityMapper; @@ -35,7 +37,7 @@ import com.gitee.dorive.core.config.RepositoryContext; import com.gitee.dorive.core.entity.common.EntityStoreInfo; import com.gitee.dorive.core.entity.executor.OrderBy; import com.gitee.dorive.core.entity.factory.FieldConverter; -import com.gitee.dorive.core.impl.context.SelectTypeMatcher; +import com.gitee.dorive.core.impl.context.AdaptiveMatcher; import com.gitee.dorive.core.impl.executor.ContextExecutor; import com.gitee.dorive.core.impl.executor.ExampleExecutor; import com.gitee.dorive.core.impl.executor.FactoryExecutor; @@ -43,8 +45,11 @@ import com.gitee.dorive.core.impl.factory.DefaultEntityFactory; import com.gitee.dorive.core.impl.factory.OperationFactory; import com.gitee.dorive.core.impl.factory.ValueObjEntityFactory; import com.gitee.dorive.core.impl.handler.BatchEntityHandler; +import com.gitee.dorive.core.impl.handler.eo.BatchEntityOpHandler; +import com.gitee.dorive.core.impl.handler.DelegatedEntityHandler; +import com.gitee.dorive.core.impl.handler.eo.DelegatedEntityOpHandler; import com.gitee.dorive.core.impl.resolver.BinderResolver; -import com.gitee.dorive.core.impl.resolver.DerivedResolver; +import com.gitee.dorive.core.impl.resolver.DerivedRepositoryResolver; import com.gitee.dorive.core.impl.resolver.EntityMapperResolver; import lombok.Getter; import lombok.Setter; @@ -61,11 +66,12 @@ import java.util.*; public abstract class AbstractContextRepository extends AbstractRepository implements ApplicationContextAware, InitializingBean { private ApplicationContext applicationContext; + private RepositoryDef repositoryDef; private Map repositoryMap = new LinkedHashMap<>(); private CommonRepository rootRepository; private List subRepositories = new ArrayList<>(); private List orderedRepositories = new ArrayList<>(); - private DerivedResolver derivedResolver; + private DerivedRepositoryResolver derivedRepositoryResolver; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { @@ -74,7 +80,11 @@ public abstract class AbstractContextRepository extends AbstractRepositor @Override public void afterPropertiesSet() throws Exception { - Class entityClass = ReflectUtils.getFirstArgumentType(this.getClass()); + Class repositoryClass = this.getClass(); + repositoryDef = RepositoryDef.fromElement(repositoryClass); + Assert.notNull(repositoryDef, "The @Repository does not exist! type: {}", repositoryClass.getName()); + Class entityClass = ReflectUtils.getFirstArgumentType(repositoryClass); + processRepositoryDef(repositoryClass, entityClass); EntityDefinitionResolver entityDefinitionResolver = new EntityDefinitionResolver(); EntityDefinition entityDefinition = entityDefinitionResolver.resolve(entityClass); @@ -98,9 +108,16 @@ public abstract class AbstractContextRepository extends AbstractRepositor setEntityElement(rootRepository.getEntityElement()); setOperationFactory(rootRepository.getOperationFactory()); - derivedResolver = new DerivedResolver(this); - EntityHandler entityHandler = processEntityHandler(new BatchEntityHandler(this)); - Executor executor = new ContextExecutor(this, entityHandler); + EntityHandler entityHandler = new BatchEntityHandler(this); + entityHandler = processEntityHandler(entityHandler); + EntityOpHandler entityOpHandler = new BatchEntityOpHandler(this); + derivedRepositoryResolver = new DerivedRepositoryResolver(this); + derivedRepositoryResolver.resolve(); + if (derivedRepositoryResolver.hasDerived()) { + entityHandler = new DelegatedEntityHandler(this, derivedRepositoryResolver.getEntityHandlerMap(entityHandler)); + entityOpHandler = new DelegatedEntityOpHandler(this, derivedRepositoryResolver.getEntityOpHandlerMap(entityOpHandler)); + } + Executor executor = new ContextExecutor(this, entityHandler, entityOpHandler); setExecutor(executor); } @@ -132,7 +149,7 @@ public abstract class AbstractContextRepository extends AbstractRepositor repository.setBinderResolver(binderResolver); repository.setDefaultOrderBy(defaultOrderBy); repository.setBound(false); - repository.setMatcher(new SelectTypeMatcher(repository)); + repository.setMatcher(new AdaptiveMatcher(repository)); return repository; } @@ -213,6 +230,8 @@ public abstract class AbstractContextRepository extends AbstractRepositor return null; } + protected abstract void processRepositoryDef(Class repositoryClass, Class entityClass); + protected abstract EntityStoreInfo resolveEntityStoreInfo(EntityElement entityElement); protected abstract Executor newExecutor(EntityElement entityElement, EntityStoreInfo entityStoreInfo); 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 b92c10bf8ef12dec19c3f65e6afeac80a23f61db..0b2c8462ebec24d353ebca6f04e88684fb26e2ae 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 @@ -72,6 +72,10 @@ public class CommonRepository extends AbstractProxyRepository implements Matcher return binderResolver.getMergedStrongBindersMap().get("/"); } + public boolean hasValueRouteBinders() { + return !binderResolver.getValueRouteBinders().isEmpty(); + } + @Override public boolean matches(Options options) { return matcher.matches(options); diff --git a/dorive-env/pom.xml b/dorive-env/pom.xml index bd1343ef6f20ef4e8125c00d1e68d10a0342cb44..10c60b4b90393483556483355e0249cce62bb2c9 100644 --- a/dorive-env/pom.xml +++ b/dorive-env/pom.xml @@ -6,7 +6,7 @@ com.gitee.digital-engine dorive - 3.5.0.3 + 3.5.0.4 dorive-env diff --git a/dorive-event/pom.xml b/dorive-event/pom.xml index bcedfd5da280caa88db710b81720cedb5cc53cc8..f7cbb7d16e9cb0c784990926b8053bd75824764f 100644 --- a/dorive-event/pom.xml +++ b/dorive-event/pom.xml @@ -6,7 +6,7 @@ com.gitee.digital-engine dorive - 3.5.0.3 + 3.5.0.4 dorive-event diff --git a/dorive-event/src/main/java/com/gitee/dorive/event/entity/EntityEvent.java b/dorive-event/src/main/java/com/gitee/dorive/event/entity/BaseEvent.java similarity index 61% rename from dorive-event/src/main/java/com/gitee/dorive/event/entity/EntityEvent.java rename to dorive-event/src/main/java/com/gitee/dorive/event/entity/BaseEvent.java index 55eea27e3b4d6e162aeed9a05714922fd531b14f..0680a8553d8246d827b68e9263e62da7c0eb038c 100644 --- a/dorive-event/src/main/java/com/gitee/dorive/event/entity/EntityEvent.java +++ b/dorive-event/src/main/java/com/gitee/dorive/event/entity/BaseEvent.java @@ -17,42 +17,28 @@ package com.gitee.dorive.event.entity; -import com.gitee.dorive.api.constant.event.Event; import com.gitee.dorive.core.api.context.Context; import com.gitee.dorive.core.entity.operation.EntityOp; -import com.gitee.dorive.core.entity.operation.eop.Delete; -import com.gitee.dorive.core.entity.operation.eop.Insert; -import com.gitee.dorive.core.entity.operation.eop.Update; import lombok.Getter; import lombok.Setter; import org.springframework.context.ApplicationEvent; - -import java.util.List; +import org.springframework.core.ResolvableType; +import org.springframework.core.ResolvableTypeProvider; @Getter @Setter -public class EntityEvent extends ApplicationEvent { - private String publisher; +public abstract class BaseEvent extends ApplicationEvent implements ResolvableTypeProvider { + private boolean root; private Class entityClass; - private String name; private Context context; - private boolean root; - private List entities; - - public static String getEventName(EntityOp entityOp) { - if (entityOp instanceof Insert) { - return Event.INSERT; + private EntityOp entityOp; - } else if (entityOp instanceof Update) { - return Event.UPDATE; - - } else if (entityOp instanceof Delete) { - return Event.DELETE; - } - return null; + public BaseEvent(Object source) { + super(source); } - public EntityEvent(Object source) { - super(source); + @Override + public ResolvableType getResolvableType() { + return ResolvableType.forClassWithGenerics(getClass(), ResolvableType.forClass(entityClass)); } } 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/entity/ExecutorEvent.java similarity index 78% rename from dorive-event/src/main/java/com/gitee/dorive/event/api/EntityEventListener.java rename to dorive-event/src/main/java/com/gitee/dorive/event/entity/ExecutorEvent.java index fb6116ce69fe3922c8e2bb57ecbf38aa1d0171fd..8444ff039b69d86c18b4ccf87d8b10155afce707 100644 --- a/dorive-event/src/main/java/com/gitee/dorive/event/api/EntityEventListener.java +++ b/dorive-event/src/main/java/com/gitee/dorive/event/entity/ExecutorEvent.java @@ -15,12 +15,15 @@ * limitations under the License. */ -package com.gitee.dorive.event.api; +package com.gitee.dorive.event.entity; -import com.gitee.dorive.event.entity.EntityEvent; - -public interface EntityEventListener { - - void onEntityEvent(EntityEvent entityEvent); +import lombok.Getter; +import lombok.Setter; +@Getter +@Setter +public class ExecutorEvent extends BaseEvent { + public ExecutorEvent(Object source) { + super(source); + } } diff --git a/dorive-api/src/main/java/com/gitee/dorive/api/constant/event/Publisher.java b/dorive-event/src/main/java/com/gitee/dorive/event/entity/RepositoryEvent.java similarity index 78% rename from dorive-api/src/main/java/com/gitee/dorive/api/constant/event/Publisher.java rename to dorive-event/src/main/java/com/gitee/dorive/event/entity/RepositoryEvent.java index fb589626fc052dd1e24a7c95deb45c217de8e20f..fb2944f942bf94de49eaf1212cbf0236260d457e 100644 --- a/dorive-api/src/main/java/com/gitee/dorive/api/constant/event/Publisher.java +++ b/dorive-event/src/main/java/com/gitee/dorive/event/entity/RepositoryEvent.java @@ -15,9 +15,15 @@ * limitations under the License. */ -package com.gitee.dorive.api.constant.event; +package com.gitee.dorive.event.entity; -public interface Publisher { - String EXECUTOR = "EXECUTOR"; - String REPOSITORY = "REPOSITORY"; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class RepositoryEvent extends BaseEvent { + public RepositoryEvent(Object source) { + super(source); + } } diff --git a/dorive-event/src/main/java/com/gitee/dorive/event/entity/ext/ExecutorDeleteEvent.java b/dorive-event/src/main/java/com/gitee/dorive/event/entity/ext/ExecutorDeleteEvent.java new file mode 100644 index 0000000000000000000000000000000000000000..f9320b6bc161ff3d5932eb01588836c8726b5df8 --- /dev/null +++ b/dorive-event/src/main/java/com/gitee/dorive/event/entity/ext/ExecutorDeleteEvent.java @@ -0,0 +1,30 @@ +/* + * 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.entity.ext; + +import com.gitee.dorive.event.entity.ExecutorEvent; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class ExecutorDeleteEvent extends ExecutorEvent { + public ExecutorDeleteEvent(Object source) { + super(source); + } +} diff --git a/dorive-event/src/main/java/com/gitee/dorive/event/entity/ext/ExecutorInsertEvent.java b/dorive-event/src/main/java/com/gitee/dorive/event/entity/ext/ExecutorInsertEvent.java new file mode 100644 index 0000000000000000000000000000000000000000..e4b3cb6dbbb3b2084822d812b0a6bc1ea40381a3 --- /dev/null +++ b/dorive-event/src/main/java/com/gitee/dorive/event/entity/ext/ExecutorInsertEvent.java @@ -0,0 +1,30 @@ +/* + * 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.entity.ext; + +import com.gitee.dorive.event.entity.ExecutorEvent; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class ExecutorInsertEvent extends ExecutorEvent { + public ExecutorInsertEvent(Object source) { + super(source); + } +} diff --git a/dorive-event/src/main/java/com/gitee/dorive/event/entity/ext/ExecutorUpdateEvent.java b/dorive-event/src/main/java/com/gitee/dorive/event/entity/ext/ExecutorUpdateEvent.java new file mode 100644 index 0000000000000000000000000000000000000000..515bc4dad031c4e65694e92f375fe74d3d503dff --- /dev/null +++ b/dorive-event/src/main/java/com/gitee/dorive/event/entity/ext/ExecutorUpdateEvent.java @@ -0,0 +1,30 @@ +/* + * 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.entity.ext; + +import com.gitee.dorive.event.entity.ExecutorEvent; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class ExecutorUpdateEvent extends ExecutorEvent { + public ExecutorUpdateEvent(Object source) { + super(source); + } +} diff --git a/dorive-event/src/main/java/com/gitee/dorive/event/entity/ext/RepositoryDeleteEvent.java b/dorive-event/src/main/java/com/gitee/dorive/event/entity/ext/RepositoryDeleteEvent.java new file mode 100644 index 0000000000000000000000000000000000000000..832736c43d5927bb825133368963fe7eb1a2181c --- /dev/null +++ b/dorive-event/src/main/java/com/gitee/dorive/event/entity/ext/RepositoryDeleteEvent.java @@ -0,0 +1,30 @@ +/* + * 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.entity.ext; + +import com.gitee.dorive.event.entity.RepositoryEvent; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class RepositoryDeleteEvent extends RepositoryEvent { + public RepositoryDeleteEvent(Object source) { + super(source); + } +} diff --git a/dorive-event/src/main/java/com/gitee/dorive/event/entity/ext/RepositoryInsertEvent.java b/dorive-event/src/main/java/com/gitee/dorive/event/entity/ext/RepositoryInsertEvent.java new file mode 100644 index 0000000000000000000000000000000000000000..e849aa5f85ab1439ededdbb77384c081a25c1ad9 --- /dev/null +++ b/dorive-event/src/main/java/com/gitee/dorive/event/entity/ext/RepositoryInsertEvent.java @@ -0,0 +1,30 @@ +/* + * 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.entity.ext; + +import com.gitee.dorive.event.entity.RepositoryEvent; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class RepositoryInsertEvent extends RepositoryEvent { + public RepositoryInsertEvent(Object source) { + super(source); + } +} diff --git a/dorive-event/src/main/java/com/gitee/dorive/event/entity/ext/RepositoryUpdateEvent.java b/dorive-event/src/main/java/com/gitee/dorive/event/entity/ext/RepositoryUpdateEvent.java new file mode 100644 index 0000000000000000000000000000000000000000..56ebccff472a5ff52ee448f4e14a10c418515b43 --- /dev/null +++ b/dorive-event/src/main/java/com/gitee/dorive/event/entity/ext/RepositoryUpdateEvent.java @@ -0,0 +1,30 @@ +/* + * 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.entity.ext; + +import com.gitee.dorive.event.entity.RepositoryEvent; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class RepositoryUpdateEvent extends RepositoryEvent { + public RepositoryUpdateEvent(Object source) { + super(source); + } +} diff --git a/dorive-event/src/main/java/com/gitee/dorive/event/impl/executor/EventExecutor.java b/dorive-event/src/main/java/com/gitee/dorive/event/impl/executor/EventExecutor.java index 0783af59f9fd444160483bf2637be6cd35550842..7c16253a090b420aa1325898709f655fb219c00a 100644 --- a/dorive-event/src/main/java/com/gitee/dorive/event/impl/executor/EventExecutor.java +++ b/dorive-event/src/main/java/com/gitee/dorive/event/impl/executor/EventExecutor.java @@ -17,14 +17,14 @@ package com.gitee.dorive.event.impl.executor; -import com.gitee.dorive.api.constant.event.Publisher; import com.gitee.dorive.api.entity.core.EntityElement; import com.gitee.dorive.core.api.context.Context; import com.gitee.dorive.core.api.executor.Executor; import com.gitee.dorive.core.entity.operation.EntityOp; import com.gitee.dorive.core.entity.operation.Operation; import com.gitee.dorive.core.impl.executor.AbstractProxyExecutor; -import com.gitee.dorive.event.entity.EntityEvent; +import com.gitee.dorive.event.entity.BaseEvent; +import com.gitee.dorive.event.impl.factory.EventFactory; import lombok.Getter; import lombok.Setter; import org.springframework.context.ApplicationContext; @@ -49,16 +49,8 @@ public class EventExecutor extends AbstractProxyExecutor { if (operation instanceof EntityOp) { Class entityClass = getEntityElement().getGenericType(); EntityOp entityOp = (EntityOp) operation; - - EntityEvent entityEvent = new EntityEvent(this); - entityEvent.setPublisher(Publisher.EXECUTOR); - entityEvent.setEntityClass(entityClass); - entityEvent.setName(EntityEvent.getEventName(entityOp)); - entityEvent.setContext(context); - entityEvent.setRoot(entityOp.isUncontrolled()); - entityEvent.setEntities(entityOp.getEntities()); - - getApplicationContext().publishEvent(entityEvent); + BaseEvent baseEvent = EventFactory.newExecutorEvent(this, entityOp.isUncontrolled(), entityClass, context, entityOp); + getApplicationContext().publishEvent(baseEvent); } } return totalCount; diff --git a/dorive-event/src/main/java/com/gitee/dorive/event/impl/listener/EventListener.java b/dorive-event/src/main/java/com/gitee/dorive/event/impl/factory/EventFactory.java similarity index 30% rename from dorive-event/src/main/java/com/gitee/dorive/event/impl/listener/EventListener.java rename to dorive-event/src/main/java/com/gitee/dorive/event/impl/factory/EventFactory.java index 9b03aafb9a0ded06086e310e5a3ec19eeac4ca0d..ac37780cbd874b64686439d8885956884a0f88b4 100644 --- a/dorive-event/src/main/java/com/gitee/dorive/event/impl/listener/EventListener.java +++ b/dorive-event/src/main/java/com/gitee/dorive/event/impl/factory/EventFactory.java @@ -15,41 +15,56 @@ * limitations under the License. */ -package com.gitee.dorive.event.impl.listener; +package com.gitee.dorive.event.impl.factory; -import com.gitee.dorive.api.entity.event.def.ListenerDef; -import com.gitee.dorive.event.api.EntityEventListener; -import com.gitee.dorive.event.entity.EntityEvent; -import com.gitee.dorive.event.impl.listener.adapter.RouteListenerAdapter; -import com.gitee.dorive.event.impl.listener.adapter.TransactionListenerAdapter; -import org.springframework.context.ApplicationListener; +import com.gitee.dorive.core.api.context.Context; +import com.gitee.dorive.core.entity.operation.EntityOp; +import com.gitee.dorive.core.entity.operation.eop.Delete; +import com.gitee.dorive.core.entity.operation.eop.Insert; +import com.gitee.dorive.core.entity.operation.eop.Update; +import com.gitee.dorive.event.entity.BaseEvent; +import com.gitee.dorive.event.entity.ext.*; -import java.util.List; +public class EventFactory { -public class EventListener extends AbstractEventListener implements ApplicationListener { + public static BaseEvent newExecutorEvent(Object source, boolean root, Class entityClass, Context context, EntityOp entityOp) { + BaseEvent baseEvent = null; + if (entityOp instanceof Insert) { + baseEvent = new ExecutorInsertEvent<>(source); - @Override - protected Class getBeanType() { - return EntityEventListener.class; - } + } else if (entityOp instanceof Update) { + baseEvent = new ExecutorUpdateEvent<>(source); - @Override - protected EntityEventListener newAdapter(Integer order, ListenerDef listenerDef, Object bean) { - EntityEventListener listener = (EntityEventListener) bean; - listener = new TransactionListenerAdapter(order, listenerDef, listener); - listener = new RouteListenerAdapter(listenerDef, listener); - return listener; + } else if (entityOp instanceof Delete) { + baseEvent = new ExecutorDeleteEvent<>(source); + } + if (baseEvent != null) { + baseEvent.setRoot(root); + baseEvent.setEntityClass(entityClass); + baseEvent.setContext(context); + baseEvent.setEntityOp(entityOp); + } + return baseEvent; } - @Override - public void onApplicationEvent(EntityEvent entityEvent) { - Class entityClass = entityEvent.getEntityClass(); - List existAdapters = getClassAdaptersMap().get(entityClass); - if (existAdapters != null && !existAdapters.isEmpty()) { - for (EntityEventListener adapter : existAdapters) { - adapter.onEntityEvent(entityEvent); - } + public static BaseEvent newRepositoryEvent(Object source, boolean root, Class entityClass, Context context, EntityOp entityOp) { + BaseEvent baseEvent = null; + if (entityOp instanceof Insert) { + baseEvent = new RepositoryInsertEvent<>(source); + + } else if (entityOp instanceof Update) { + baseEvent = new RepositoryUpdateEvent<>(source); + + } else if (entityOp instanceof Delete) { + baseEvent = new RepositoryDeleteEvent<>(source); + } + if (baseEvent != null) { + baseEvent.setRoot(root); + baseEvent.setEntityClass(entityClass); + baseEvent.setContext(context); + baseEvent.setEntityOp(entityOp); } + return baseEvent; } } diff --git a/dorive-event/src/main/java/com/gitee/dorive/event/impl/listener/AbstractEventListener.java b/dorive-event/src/main/java/com/gitee/dorive/event/impl/listener/AbstractEventListener.java deleted file mode 100644 index 97de8b0a1313716f52cdff56eca162253dde8218..0000000000000000000000000000000000000000 --- a/dorive-event/src/main/java/com/gitee/dorive/event/impl/listener/AbstractEventListener.java +++ /dev/null @@ -1,78 +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.event.impl.listener; - -import com.gitee.dorive.api.entity.event.def.ListenerDef; -import com.gitee.dorive.event.api.EntityEventListener; -import lombok.Data; -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; -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; - -@Data -public abstract class AbstractEventListener implements ApplicationContextAware, InitializingBean { - - private ApplicationContext applicationContext; - private final Map, List> classAdaptersMap = new ConcurrentHashMap<>(); - - @Override - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - this.applicationContext = applicationContext; - } - - @Override - public void afterPropertiesSet() { - Map beanMap = applicationContext.getBeansOfType(getBeanType()); - List beans = new ArrayList<>(beanMap.values()); - AnnotationAwareOrderComparator.sort(beans); - for (Object bean : beans) { - Class listenerType = bean.getClass(); - Integer order = OrderUtils.getOrder(listenerType, LOWEST_PRECEDENCE); - ListenerDef listenerDef = ListenerDef.fromElement(listenerType); - registry(order, listenerDef, bean); - } - } - - public void registry(Integer order, ListenerDef listenerDef, Object bean) { - if (listenerDef == null) { - return; - } - Class entityClass = listenerDef.getEntityClass(); - if (entityClass == null) { - return; - } - EntityEventListener adapter = newAdapter(order, listenerDef, bean); - List existAdapters = classAdaptersMap.computeIfAbsent(entityClass, key -> new ArrayList<>(4)); - existAdapters.add(adapter); - } - - protected abstract Class getBeanType(); - - protected abstract EntityEventListener newAdapter(Integer order, ListenerDef listenerDef, Object bean); - -} diff --git a/dorive-event/src/main/java/com/gitee/dorive/event/impl/listener/adapter/TransactionListenerAdapter.java b/dorive-event/src/main/java/com/gitee/dorive/event/impl/listener/adapter/TransactionListenerAdapter.java deleted file mode 100644 index 542c73bf7189a759edcf1cb49813d77b2ffad884..0000000000000000000000000000000000000000 --- a/dorive-event/src/main/java/com/gitee/dorive/event/impl/listener/adapter/TransactionListenerAdapter.java +++ /dev/null @@ -1,104 +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.event.impl.listener.adapter; - -import com.gitee.dorive.api.entity.event.def.ListenerDef; -import com.gitee.dorive.event.api.EntityEventListener; -import com.gitee.dorive.event.entity.EntityEvent; -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 TransactionListenerAdapter implements EntityEventListener { - - private Integer order; - private ListenerDef listenerDef; - private EntityEventListener entityEventListener; - - @Override - public void onEntityEvent(EntityEvent entityEvent) { - boolean isTxActive = listenerDef.isAfterCommit() && TransactionSynchronizationManager.isActualTransactionActive(); - if (!isTxActive) { - handleEntityEvent(entityEvent, true); - } else { - handleEntityEventWhenTxActive(entityEvent); - } - } - - private void handleEntityEvent(EntityEvent entityEvent, boolean canThrowException) { - try { - entityEventListener.onEntityEvent(entityEvent); - - } catch (Throwable throwable) { - if (canThrowException && matchThrowExceptions(throwable)) { - throw throwable; - } - log.error("Exception occurred in entity event listening!", throwable); - } - } - - private boolean matchThrowExceptions(Throwable throwable) { - Class[] throwExceptions = listenerDef.getThrowExceptions(); - if (throwExceptions != null && throwExceptions.length != 0) { - Class throwableType = throwable.getClass(); - for (Class throwExceptionType : throwExceptions) { - if (throwExceptionType.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/repository/AbstractEventRepository.java b/dorive-event/src/main/java/com/gitee/dorive/event/repository/AbstractEventRepository.java index 038acab01410350fe25d025baa763cbf90da3507..3784389dc1cdf13a3f25cbacfbb2eab8b3815573 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 @@ -17,9 +17,9 @@ package com.gitee.dorive.event.repository; -import com.gitee.dorive.api.annotation.event.EnableEvent; -import com.gitee.dorive.api.constant.event.Publisher; +import cn.hutool.core.util.ArrayUtil; import com.gitee.dorive.api.entity.core.EntityElement; +import com.gitee.dorive.api.entity.core.def.RepositoryDef; import com.gitee.dorive.core.api.context.Context; import com.gitee.dorive.core.api.executor.Executor; import com.gitee.dorive.core.entity.operation.EntityOp; @@ -31,24 +31,28 @@ 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; -import com.gitee.dorive.event.entity.EntityEvent; +import com.gitee.dorive.event.entity.BaseEvent; +import com.gitee.dorive.event.entity.ExecutorEvent; +import com.gitee.dorive.event.entity.RepositoryEvent; import com.gitee.dorive.event.impl.executor.EventExecutor; -import org.springframework.core.annotation.AnnotationUtils; +import com.gitee.dorive.event.impl.factory.EventFactory; public abstract class AbstractEventRepository extends AbstractGenericRepository { - private boolean enableEvent; + private boolean enableExecutorEvent; + private boolean enableRepositoryEvent; @Override - public void afterPropertiesSet() throws Exception { - EnableEvent enableEvent = AnnotationUtils.getAnnotation(this.getClass(), EnableEvent.class); - this.enableEvent = enableEvent != null; - super.afterPropertiesSet(); + protected void processRepositoryDef(Class repositoryClass, Class entityClass) { + RepositoryDef repositoryDef = getRepositoryDef(); + Class[] events = repositoryDef.getEvents(); + enableExecutorEvent = ArrayUtil.contains(events, ExecutorEvent.class); + enableRepositoryEvent = ArrayUtil.contains(events, RepositoryEvent.class); } @Override protected AbstractRepository processRepository(AbstractRepository repository) { - if (enableEvent) { + if (enableExecutorEvent) { AbstractRepository actualRepository = repository; if (repository instanceof AbstractProxyRepository) { actualRepository = ((AbstractProxyRepository) repository).getProxyRepository(); @@ -67,7 +71,7 @@ public abstract class AbstractEventRepository extends AbstractGenericRepo @Override public int execute(Context context, Operation operation) { int totalCount = super.execute(context, operation); - if (enableEvent && totalCount != 0) { + if (enableRepositoryEvent && totalCount != 0) { if (operation instanceof InsertOrUpdate) { InsertOrUpdate insertOrUpdate = (InsertOrUpdate) operation; Insert insert = insertOrUpdate.getInsert(); @@ -89,16 +93,8 @@ public abstract class AbstractEventRepository extends AbstractGenericRepo if (operation instanceof EntityOp) { Class entityClass = getEntityElement().getGenericType(); EntityOp entityOp = (EntityOp) operation; - - EntityEvent entityEvent = new EntityEvent(this); - entityEvent.setPublisher(Publisher.REPOSITORY); - entityEvent.setEntityClass(entityClass); - entityEvent.setName(EntityEvent.getEventName(entityOp)); - entityEvent.setContext(context); - entityEvent.setRoot(entityOp.isUncontrolled()); - entityEvent.setEntities(entityOp.getEntities()); - - getApplicationContext().publishEvent(entityEvent); + BaseEvent baseEvent = EventFactory.newRepositoryEvent(this, entityOp.isUncontrolled(), entityClass, context, entityOp); + getApplicationContext().publishEvent(baseEvent); } } diff --git a/dorive-event/src/main/resources/META-INF/spring.factories b/dorive-event/src/main/resources/META-INF/spring.factories deleted file mode 100644 index bbb14a20ec01e8e36902a0aafe8781a47aa9ede1..0000000000000000000000000000000000000000 --- a/dorive-event/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,2 +0,0 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ - com.gitee.dorive.event.config.DoriveEventConfiguration \ No newline at end of file diff --git a/dorive-event/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/dorive-event/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports deleted file mode 100644 index 736ff4700f12401fc74d4a5c75f22d5ad10d3b87..0000000000000000000000000000000000000000 --- a/dorive-event/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ /dev/null @@ -1 +0,0 @@ -com.gitee.dorive.event.config.DoriveEventConfiguration \ No newline at end of file diff --git a/dorive-inject/pom.xml b/dorive-inject/pom.xml index 037cd731ce5a8feb0d006c3b590ff364a678ab27..d13f899f8b82044dcc64684f3130f3dd0060371e 100644 --- a/dorive-inject/pom.xml +++ b/dorive-inject/pom.xml @@ -6,7 +6,7 @@ com.gitee.digital-engine dorive - 3.5.0.3 + 3.5.0.4 dorive-inject diff --git a/dorive-mybatis-plus/pom.xml b/dorive-mybatis-plus/pom.xml index 45f66c9c1f763a42550ff3026a695e988c1e0c9c..c0806292e19f775780ff9651ece7458921b52019 100644 --- a/dorive-mybatis-plus/pom.xml +++ b/dorive-mybatis-plus/pom.xml @@ -6,7 +6,7 @@ com.gitee.digital-engine dorive - 3.5.0.3 + 3.5.0.4 dorive-mybatis-plus diff --git a/dorive-mybatis-plus/src/main/java/com/gitee/dorive/mybatis/plus/repository/MybatisPlusRepository.java b/dorive-mybatis-plus/src/main/java/com/gitee/dorive/mybatis/plus/repository/MybatisPlusRepository.java index 758164bad21f8e546540c563a5a04ad9e20077c5..b73bbc280b6a36ea95445aa860c80f81ff1f423b 100644 --- a/dorive-mybatis-plus/src/main/java/com/gitee/dorive/mybatis/plus/repository/MybatisPlusRepository.java +++ b/dorive-mybatis-plus/src/main/java/com/gitee/dorive/mybatis/plus/repository/MybatisPlusRepository.java @@ -23,23 +23,23 @@ 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.core.api.common.ImplFactory; -import com.gitee.dorive.api.entity.core.def.EntityDef; import com.gitee.dorive.api.entity.core.EntityElement; +import com.gitee.dorive.api.entity.core.def.EntityDef; +import com.gitee.dorive.core.api.common.ImplFactory; 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.enums.QueryMethod; import com.gitee.dorive.mybatis.plus.executor.MybatisPlusExecutor; -import com.gitee.dorive.query.api.QueryExecutor; -import com.gitee.dorive.query.entity.QueryContext; +import com.gitee.dorive.query.api.QueryHandler; +import com.gitee.dorive.query.entity.enums.QueryMethod; import com.gitee.dorive.ref.repository.AbstractRefRepository; import com.gitee.dorive.sql.api.CountQuerier; import com.gitee.dorive.sql.api.SqlRunner; import com.gitee.dorive.sql.entity.common.CountQuery; -import com.gitee.dorive.sql.impl.executor.CountSqlQueryExecutor; -import com.gitee.dorive.sql.impl.executor.SqlQueryExecutor; import com.gitee.dorive.sql.impl.executor.UnionExecutor; +import com.gitee.dorive.sql.impl.handler.SqlBuildQueryHandler; +import com.gitee.dorive.sql.impl.handler.SqlExecuteQueryHandler; +import com.gitee.dorive.sql.impl.querier.SqlCountQuerier; import lombok.Getter; import lombok.Setter; import org.apache.commons.lang3.StringUtils; @@ -56,27 +56,25 @@ import java.util.Map; public class MybatisPlusRepository extends AbstractRefRepository implements CountQuerier { 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); - this.sqlQueryExecutor = new SqlQueryExecutor(this, this.sqlRunner); - this.countQuerier = new CountSqlQueryExecutor(this, this.sqlRunner); super.afterPropertiesSet(); + this.countQuerier = new SqlCountQuerier(this, getQueryHandler(), this.sqlRunner); } @Override protected EntityStoreInfo resolveEntityStoreInfo(EntityElement entityElement) { EntityDef entityDef = entityElement.getEntityDef(); - Class mapperClass = entityDef.getSource(); + Class mapperClass = entityDef.getDataSource(); Object mapper = null; Class pojoClass = null; if (mapperClass != Object.class) { mapper = getApplicationContext().getBean(mapperClass); - Assert.notNull(mapper, "The mapper cannot be null! source: {}", mapperClass); + Assert.notNull(mapper, "The mapper cannot be null! data source: {}", mapperClass); Type[] genericInterfaces = mapperClass.getGenericInterfaces(); if (genericInterfaces.length > 0) { Type genericInterface = mapperClass.getGenericInterfaces()[0]; @@ -88,9 +86,9 @@ public class MybatisPlusRepository extends AbstractRefRepository i } } - Assert.notNull(pojoClass, "The class of pojo cannot be null! source: {}", mapperClass); + Assert.notNull(pojoClass, "The class of pojo cannot be null! data source: {}", mapperClass); TableInfo tableInfo = TableInfoHelper.getTableInfo(pojoClass); - Assert.notNull(tableInfo, "The table info cannot be null! source: {}", mapperClass); + Assert.notNull(tableInfo, "The table info cannot be null! data source: {}", mapperClass); assert tableInfo != null; return newEntityStoreInfo(mapperClass, mapper, pojoClass, tableInfo); } @@ -128,13 +126,10 @@ public class MybatisPlusRepository extends AbstractRefRepository i } @Override - protected QueryExecutor adaptiveQueryExecutor(QueryContext queryContext) { - Context context = queryContext.getContext(); - QueryMethod queryMethod = context.getOption(QueryMethod.class); - if (queryMethod == null || queryMethod == QueryMethod.SQL) { - return sqlQueryExecutor; - } - return super.adaptiveQueryExecutor(queryContext); + protected void registryQueryHandlers(Map queryHandlerMap) { + super.registryQueryHandlers(queryHandlerMap); + queryHandlerMap.put(QueryMethod.SQL_BUILD, new SqlBuildQueryHandler(this, null)); + queryHandlerMap.put(QueryMethod.SQL_EXECUTE, new SqlExecuteQueryHandler(this, null, sqlRunner)); } @Override diff --git a/dorive-query/pom.xml b/dorive-query/pom.xml index db3ba97eac02979aeb8d2761f6c4557df3567753..6dfed7fc2bc4750e4a3b9f7335bf87455d1c1774 100644 --- a/dorive-query/pom.xml +++ b/dorive-query/pom.xml @@ -6,7 +6,7 @@ com.gitee.digital-engine dorive - 3.5.0.3 + 3.5.0.4 dorive-query 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/QueryHandler.java similarity index 85% rename from dorive-query/src/main/java/com/gitee/dorive/query/api/QueryExecutor.java rename to dorive-query/src/main/java/com/gitee/dorive/query/api/QueryHandler.java index 6c5f9f51bfaeae00e21314b275f0619c0b3ab6ab..4407ab170083c2f1fd8209ffb52bfdbcd52ea3fd 100644 --- a/dorive-query/src/main/java/com/gitee/dorive/query/api/QueryExecutor.java +++ b/dorive-query/src/main/java/com/gitee/dorive/query/api/QueryHandler.java @@ -17,11 +17,10 @@ package com.gitee.dorive.query.api; -import com.gitee.dorive.core.entity.executor.Result; import com.gitee.dorive.query.entity.QueryContext; -public interface QueryExecutor { +public interface QueryHandler { - Result executeQuery(QueryContext queryContext); + void handle(QueryContext queryContext, Object query); } 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 index 8895cf33d45d4179c2e99740abdbc39f102404b7..8e83efd2b4d4d6e4c9f64a5a6d0c63b54969b749 100644 --- 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 @@ -18,55 +18,47 @@ package com.gitee.dorive.query.entity; import com.gitee.dorive.core.api.context.Context; +import com.gitee.dorive.core.entity.context.AbstractProxyContext; 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.QueryExampleResolver; -import lombok.Data; +import lombok.Getter; +import lombok.Setter; -import java.util.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; -@Data -public class QueryContext { - - private Context context; - private Object query; - private ResultType resultType; +@Getter +@Setter +public class QueryContext extends AbstractProxyContext { private Class queryType; + private ResultType resultType; + private boolean abandoned; + private QueryExampleResolver queryExampleResolver; - private List mergedRepositories; private Map exampleMap; private Example example; + + private List mergedRepositories; private Map queryUnitMap; private QueryUnit queryUnit; + private List args = new ArrayList<>(8); + private Result result; - public QueryContext(Context context, Object query, ResultType resultType) { - this.context = context; - this.query = query; + public QueryContext(Context context, Class queryType, ResultType resultType) { + super(context); + this.queryType = queryType; this.resultType = resultType; - this.queryType = query.getClass(); - } - - 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!"); + public boolean isAbandoned() { + return abandoned || (queryUnit != null && queryUnit.isAbandoned()); } - } diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/entity/enums/QueryMethod.java b/dorive-query/src/main/java/com/gitee/dorive/query/entity/enums/QueryMethod.java similarity index 90% rename from dorive-core/src/main/java/com/gitee/dorive/core/entity/enums/QueryMethod.java rename to dorive-query/src/main/java/com/gitee/dorive/query/entity/enums/QueryMethod.java index ff60dc27fb6b8e6e456a17a98ba310001689e308..07c51200b93f37b92f3ca35051124bd37916e058 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/entity/enums/QueryMethod.java +++ b/dorive-query/src/main/java/com/gitee/dorive/query/entity/enums/QueryMethod.java @@ -15,9 +15,10 @@ * limitations under the License. */ -package com.gitee.dorive.core.entity.enums; +package com.gitee.dorive.query.entity.enums; public enum QueryMethod { - DEFAULT, - SQL + STEPWISE, + SQL_BUILD, + SQL_EXECUTE, } diff --git a/dorive-api/src/main/java/com/gitee/dorive/api/annotation/event/Listener.java b/dorive-query/src/main/java/com/gitee/dorive/query/impl/handler/AdaptiveQueryHandler.java similarity index 49% rename from dorive-api/src/main/java/com/gitee/dorive/api/annotation/event/Listener.java rename to dorive-query/src/main/java/com/gitee/dorive/query/impl/handler/AdaptiveQueryHandler.java index 4ad3f5c0d6a70c7a92e2d0cd424462521b5e46b4..3e60eef667f5917fd8d2da7c6fd23ec62ab9ba3a 100644 --- a/dorive-api/src/main/java/com/gitee/dorive/api/annotation/event/Listener.java +++ b/dorive-query/src/main/java/com/gitee/dorive/query/impl/handler/AdaptiveQueryHandler.java @@ -15,31 +15,30 @@ * limitations under the License. */ -package com.gitee.dorive.api.annotation.event; - -import com.gitee.dorive.api.constant.event.Event; -import com.gitee.dorive.api.constant.event.Publisher; -import org.springframework.stereotype.Component; - -import java.lang.annotation.*; - -@Component -@Inherited -@Documented -@Target(ElementType.TYPE) -@Retention(RetentionPolicy.RUNTIME) -public @interface Listener { - - String[] publishers() default {Publisher.EXECUTOR}; - - Class entityClass(); - - String[] events() default {Event.INSERT, Event.UPDATE, Event.DELETE}; - - boolean onlyRoot() default false; - - boolean afterCommit() default false; - - Class[] throwExceptions() default {}; +package com.gitee.dorive.query.impl.handler; + +import com.gitee.dorive.query.api.QueryHandler; +import com.gitee.dorive.query.entity.QueryContext; +import com.gitee.dorive.query.entity.enums.QueryMethod; +import lombok.AllArgsConstructor; + +import java.util.Map; + +@AllArgsConstructor +public class AdaptiveQueryHandler implements QueryHandler { + + private final Map queryHandlerMap; + + @Override + public void handle(QueryContext queryContext, Object query) { + QueryMethod queryMethod = queryContext.getOption(QueryMethod.class); + if (queryMethod == null) { + queryMethod = QueryMethod.SQL_EXECUTE; + } + QueryHandler queryHandler = queryHandlerMap.get(queryMethod); + if (queryHandler != null) { + queryHandler.handle(queryContext, query); + } + } } diff --git a/dorive-query/src/main/java/com/gitee/dorive/query/impl/handler/ContextMatchQueryHandler.java b/dorive-query/src/main/java/com/gitee/dorive/query/impl/handler/ContextMatchQueryHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..98b1ab2bb986c7a103227db9cf2a5220c4f709f6 --- /dev/null +++ b/dorive-query/src/main/java/com/gitee/dorive/query/impl/handler/ContextMatchQueryHandler.java @@ -0,0 +1,44 @@ +/* + * 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.handler; + +import com.gitee.dorive.core.api.context.Matcher; +import com.gitee.dorive.query.api.QueryHandler; +import com.gitee.dorive.query.entity.QueryContext; +import com.gitee.dorive.query.repository.AbstractQueryRepository; +import lombok.AllArgsConstructor; + +@AllArgsConstructor +public class ContextMatchQueryHandler implements QueryHandler { + + private final AbstractQueryRepository repository; + private final QueryHandler queryHandler; + + @Override + public void handle(QueryContext queryContext, Object query) { + Matcher matcher = repository.getRootRepository(); + if (!matcher.matches(queryContext.getContext())) { + queryContext.setAbandoned(true); + return; + } + if (queryHandler != null) { + queryHandler.handle(queryContext, query); + } + } + +} diff --git a/dorive-query/src/main/java/com/gitee/dorive/query/impl/handler/ExampleQueryHandler.java b/dorive-query/src/main/java/com/gitee/dorive/query/impl/handler/ExampleQueryHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..1813f580f857ae95c5c0a3422301df97905c1beb --- /dev/null +++ b/dorive-query/src/main/java/com/gitee/dorive/query/impl/handler/ExampleQueryHandler.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.query.impl.handler; + +import cn.hutool.core.lang.Assert; +import com.gitee.dorive.core.entity.executor.Example; +import com.gitee.dorive.query.api.QueryHandler; +import com.gitee.dorive.query.entity.QueryContext; +import com.gitee.dorive.query.impl.resolver.QueryExampleResolver; +import com.gitee.dorive.query.impl.resolver.QueryTypeResolver; +import com.gitee.dorive.query.repository.AbstractQueryRepository; +import lombok.AllArgsConstructor; + +import java.util.Map; + +@AllArgsConstructor +public class ExampleQueryHandler implements QueryHandler { + + private final AbstractQueryRepository repository; + private final QueryHandler queryHandler; + + @Override + public void handle(QueryContext queryContext, Object query) { + QueryTypeResolver queryTypeResolver = repository.getQueryTypeResolver(); + Map, QueryExampleResolver> classQueryExampleResolverMap = queryTypeResolver.getClassQueryExampleResolverMap(); + + Class queryType = queryContext.getQueryType(); + QueryExampleResolver queryExampleResolver = classQueryExampleResolverMap.get(queryType); + + Assert.notNull(queryExampleResolver, "No query resolver found!"); + queryContext.setQueryExampleResolver(queryExampleResolver); + + Map exampleMap = queryExampleResolver.resolve(query); + queryContext.setExampleMap(exampleMap); + queryContext.setExample(exampleMap.get("/")); + + if (queryHandler != null) { + queryHandler.handle(queryContext, query); + } + } + +} diff --git a/dorive-query/src/main/java/com/gitee/dorive/query/impl/executor/AbstractQueryExecutor.java b/dorive-query/src/main/java/com/gitee/dorive/query/impl/handler/QueryUnitQueryHandler.java similarity index 45% rename from dorive-query/src/main/java/com/gitee/dorive/query/impl/executor/AbstractQueryExecutor.java rename to dorive-query/src/main/java/com/gitee/dorive/query/impl/handler/QueryUnitQueryHandler.java index ebfc8b4e49419d641fa5988b20392cba83261964..e8b2a02f994d4057045a0e8706735e105fb85cef 100644 --- a/dorive-query/src/main/java/com/gitee/dorive/query/impl/executor/AbstractQueryExecutor.java +++ b/dorive-query/src/main/java/com/gitee/dorive/query/impl/handler/QueryUnitQueryHandler.java @@ -15,88 +15,57 @@ * limitations under the License. */ -package com.gitee.dorive.query.impl.executor; +package com.gitee.dorive.query.impl.handler; import cn.hutool.core.lang.Assert; -import com.gitee.dorive.core.api.context.Context; -import com.gitee.dorive.core.api.context.Matcher; 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.entity.executor.Result; -import com.gitee.dorive.query.api.QueryExecutor; +import com.gitee.dorive.query.api.QueryHandler; import com.gitee.dorive.query.entity.MergedRepository; import com.gitee.dorive.query.entity.QueryContext; import com.gitee.dorive.query.entity.QueryUnit; -import com.gitee.dorive.query.entity.enums.ResultType; import com.gitee.dorive.query.impl.resolver.QueryTypeResolver; -import com.gitee.dorive.query.impl.resolver.QueryExampleResolver; import com.gitee.dorive.query.repository.AbstractQueryRepository; +import lombok.AllArgsConstructor; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -public abstract class AbstractQueryExecutor implements QueryExecutor { +@AllArgsConstructor +public class QueryUnitQueryHandler implements QueryHandler { protected final AbstractQueryRepository repository; - - public AbstractQueryExecutor(AbstractQueryRepository repository) { - this.repository = repository; - } + protected final QueryHandler queryHandler; @Override - public Result executeQuery(QueryContext queryContext) { - resolve(queryContext); - Matcher matcher = repository.getRootRepository(); - if (!matcher.matches(queryContext.getContext())) { - return queryContext.newEmptyResult(); - } - if (queryContext.isSimpleQuery()) { - return executeRootQuery(queryContext); - } - return doExecuteQuery(queryContext); - } + public void handle(QueryContext queryContext, Object query) { + QueryTypeResolver queryTypeResolver = repository.getQueryTypeResolver(); + Map, List> classMergedRepositoriesMap = getClassMergedRepositoriesMap(queryTypeResolver); - protected void resolve(QueryContext queryContext) { Class queryType = queryContext.getQueryType(); - QueryExampleResolver queryExampleResolver = getQueryExampleResolver(queryType); - List mergedRepositories = getMergedRepositories(queryType); - Assert.notNull(queryExampleResolver, "No query resolver found!"); + List mergedRepositories = classMergedRepositoriesMap.get(queryType); + Assert.notEmpty(mergedRepositories, "The merged repositories cannot be empty!"); - queryContext.setQueryExampleResolver(queryExampleResolver); queryContext.setMergedRepositories(mergedRepositories); - Map exampleMap = newExampleMap(queryContext); - queryContext.setExampleMap(exampleMap); - queryContext.setExample(exampleMap.get("/")); - Map queryUnitMap = newQueryUnitMap(queryContext); queryContext.setQueryUnit(queryUnitMap.get("/")); - } - - protected QueryExampleResolver getQueryExampleResolver(Class queryType) { - QueryTypeResolver queryTypeResolver = repository.getQueryTypeResolver(); - Map, QueryExampleResolver> classQueryExampleResolverMap = queryTypeResolver.getClassQueryExampleResolverMap(); - return classQueryExampleResolverMap.get(queryType); - } - protected List getMergedRepositories(Class queryType) { - QueryTypeResolver queryTypeResolver = repository.getQueryTypeResolver(); - Map, List> classMergedRepositoriesMap = queryTypeResolver.getClassMergedRepositoriesMap(); - return classMergedRepositoriesMap.get(queryType); + if (queryHandler != null) { + queryHandler.handle(queryContext, query); + } } - protected Map newExampleMap(QueryContext queryContext) { - Object query = queryContext.getQuery(); - QueryExampleResolver queryExampleResolver = queryContext.getQueryExampleResolver(); - return queryExampleResolver.resolve(query); + protected Map, List> getClassMergedRepositoriesMap(QueryTypeResolver queryTypeResolver) { + return queryTypeResolver.getClassMergedRepositoriesMap(); } - protected Map newQueryUnitMap(QueryContext queryContext) { + private Map newQueryUnitMap(QueryContext queryContext) { List mergedRepositories = queryContext.getMergedRepositories(); Map exampleMap = queryContext.getExampleMap(); Map queryUnitMap = new LinkedHashMap<>(); + // 后续可能用到 queryContext.setQueryUnitMap(queryUnitMap); for (MergedRepository mergedRepository : mergedRepositories) { String absoluteAccessPath = mergedRepository.getAbsoluteAccessPath(); @@ -111,26 +80,4 @@ public abstract class AbstractQueryExecutor implements QueryExecutor { return new QueryUnit(mergedRepository, example, false); } - @SuppressWarnings("unchecked") - protected Result executeRootQuery(QueryContext queryContext) { - 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 queryContext.newEmptyResult(); - } - - protected abstract Result doExecuteQuery(QueryContext queryContext); - } diff --git a/dorive-query/src/main/java/com/gitee/dorive/query/impl/handler/SimpleQueryHandler.java b/dorive-query/src/main/java/com/gitee/dorive/query/impl/handler/SimpleQueryHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..e2ec8414a9b500e0cf942b0da29f2750d1eb5926 --- /dev/null +++ b/dorive-query/src/main/java/com/gitee/dorive/query/impl/handler/SimpleQueryHandler.java @@ -0,0 +1,43 @@ +/* + * 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.handler; + +import com.gitee.dorive.core.entity.executor.Example; +import com.gitee.dorive.query.api.QueryHandler; +import com.gitee.dorive.query.entity.QueryContext; +import lombok.AllArgsConstructor; + +import java.util.Map; + +@AllArgsConstructor +public class SimpleQueryHandler implements QueryHandler { + + private final QueryHandler queryHandler; + + @Override + public void handle(QueryContext queryContext, Object query) { + Map exampleMap = queryContext.getExampleMap(); + if (exampleMap.size() == 1 && exampleMap.containsKey("/")) { + return; + } + if (queryHandler != null) { + queryHandler.handle(queryContext, query); + } + } + +} diff --git a/dorive-query/src/main/java/com/gitee/dorive/query/impl/executor/StepwiseQueryExecutor.java b/dorive-query/src/main/java/com/gitee/dorive/query/impl/handler/StepwiseQueryHandler.java similarity index 87% rename from dorive-query/src/main/java/com/gitee/dorive/query/impl/executor/StepwiseQueryExecutor.java rename to dorive-query/src/main/java/com/gitee/dorive/query/impl/handler/StepwiseQueryHandler.java index 680a3206b971b622739ab7ba1449ed95951e743a..7589c51a80ea3771ac2e36a2c18c23143980cb75 100644 --- a/dorive-query/src/main/java/com/gitee/dorive/query/impl/executor/StepwiseQueryExecutor.java +++ b/dorive-query/src/main/java/com/gitee/dorive/query/impl/handler/StepwiseQueryHandler.java @@ -15,17 +15,17 @@ * limitations under the License. */ -package com.gitee.dorive.query.impl.executor; +package com.gitee.dorive.query.impl.handler; 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.core.impl.binder.AbstractBinder; import com.gitee.dorive.core.impl.binder.StrongBinder; import com.gitee.dorive.core.impl.binder.ValueRouteBinder; 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.api.QueryHandler; import com.gitee.dorive.query.entity.MergedRepository; import com.gitee.dorive.query.entity.QueryContext; import com.gitee.dorive.query.entity.QueryUnit; @@ -35,30 +35,21 @@ import com.gitee.dorive.query.repository.AbstractQueryRepository; import java.util.*; import java.util.stream.Collectors; -public class StepwiseQueryExecutor extends AbstractQueryExecutor { +public class StepwiseQueryHandler extends QueryUnitQueryHandler { - public StepwiseQueryExecutor(AbstractQueryRepository repository) { - super(repository); + public StepwiseQueryHandler(AbstractQueryRepository repository, QueryHandler queryHandler) { + super(repository, queryHandler); } @Override - protected List getMergedRepositories(Class queryType) { - QueryTypeResolver queryTypeResolver = repository.getQueryTypeResolver(); - Map, List> classReversedMergedRepositoriesMap = queryTypeResolver.getClassReversedMergedRepositoriesMap(); - return classReversedMergedRepositoriesMap.get(queryType); + protected Map, List> getClassMergedRepositoriesMap(QueryTypeResolver queryTypeResolver) { + return queryTypeResolver.getClassReversedMergedRepositoriesMap(); } @Override - protected Result doExecuteQuery(QueryContext queryContext) { - executeReversedQuery(queryContext); - QueryUnit queryUnit = queryContext.getQueryUnit(); - if (queryUnit.isAbandoned()) { - return queryContext.newEmptyResult(); - } - return super.executeRootQuery(queryContext); - } + public void handle(QueryContext queryContext, Object query) { + super.handle(queryContext, query); - private void executeReversedQuery(QueryContext queryContext) { Context context = queryContext.getContext(); Map queryUnitMap = queryContext.getQueryUnitMap(); diff --git a/dorive-query/src/main/java/com/gitee/dorive/query/impl/resolver/QueryTypeResolver.java b/dorive-query/src/main/java/com/gitee/dorive/query/impl/resolver/QueryTypeResolver.java index 5f0700b96466a533ef93d645fefed18136ffaeeb..8ebcc75b25fcc172ac2b8377afd15372c15146e3 100644 --- a/dorive-query/src/main/java/com/gitee/dorive/query/impl/resolver/QueryTypeResolver.java +++ b/dorive-query/src/main/java/com/gitee/dorive/query/impl/resolver/QueryTypeResolver.java @@ -18,9 +18,9 @@ package com.gitee.dorive.query.impl.resolver; import cn.hutool.core.lang.Assert; +import com.gitee.dorive.api.entity.core.def.RepositoryDef; import com.gitee.dorive.api.entity.query.QueryDefinition; import com.gitee.dorive.api.entity.query.QueryFieldDefinition; -import com.gitee.dorive.api.entity.query.def.EnableQueryDef; import com.gitee.dorive.api.entity.query.def.QueryFieldDef; import com.gitee.dorive.api.impl.query.QueryDefinitionResolver; import com.gitee.dorive.core.repository.CommonRepository; @@ -44,8 +44,8 @@ public class QueryTypeResolver { } public void resolve() { - EnableQueryDef enableQueryDef = repository.getEnableQueryDef(); - Class[] queries = enableQueryDef.getQueries(); + RepositoryDef repositoryDef = repository.getRepositoryDef(); + Class[] queries = repositoryDef.getQueries(); for (Class queryClass : queries) { resolveQueryClass(queryClass); } diff --git a/dorive-query/src/main/java/com/gitee/dorive/query/repository/AbstractQueryRepository.java b/dorive-query/src/main/java/com/gitee/dorive/query/repository/AbstractQueryRepository.java index dd21350fc1d4dba6201f1d5711931582a5c0b5ad..8ee24e4fed3939d7709c5316b5af00a68aa1c5e8 100644 --- a/dorive-query/src/main/java/com/gitee/dorive/query/repository/AbstractQueryRepository.java +++ b/dorive-query/src/main/java/com/gitee/dorive/query/repository/AbstractQueryRepository.java @@ -17,82 +17,118 @@ package com.gitee.dorive.query.repository; -import com.gitee.dorive.api.annotation.core.Repository; +import com.gitee.dorive.api.entity.core.def.RepositoryDef; 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.event.repository.AbstractEventRepository; -import com.gitee.dorive.query.api.QueryExecutor; +import com.gitee.dorive.query.api.QueryHandler; import com.gitee.dorive.query.api.QueryRepository; import com.gitee.dorive.query.entity.QueryContext; -import com.gitee.dorive.api.entity.query.def.EnableQueryDef; +import com.gitee.dorive.query.entity.enums.QueryMethod; import com.gitee.dorive.query.entity.enums.ResultType; -import com.gitee.dorive.query.impl.executor.StepwiseQueryExecutor; +import com.gitee.dorive.query.impl.handler.*; import com.gitee.dorive.query.impl.resolver.MergedRepositoryResolver; import com.gitee.dorive.query.impl.resolver.QueryTypeResolver; import lombok.Getter; import lombok.Setter; -import org.springframework.core.annotation.AnnotatedElementUtils; +import java.util.Collections; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; @Getter @Setter -public abstract class AbstractQueryRepository extends AbstractEventRepository implements QueryRepository, QueryExecutor { +public abstract class AbstractQueryRepository extends AbstractEventRepository implements QueryRepository { - private EnableQueryDef enableQueryDef; private MergedRepositoryResolver mergedRepositoryResolver; private QueryTypeResolver queryTypeResolver; - private QueryExecutor stepwiseQueryExecutor; + private QueryHandler queryHandler; @Override public void afterPropertiesSet() throws Exception { super.afterPropertiesSet(); - Repository repository = AnnotatedElementUtils.getMergedAnnotation(this.getClass(), Repository.class); - this.enableQueryDef = EnableQueryDef.fromElement(this.getClass()); - if (repository != null) { - this.mergedRepositoryResolver = new MergedRepositoryResolver(this); - mergedRepositoryResolver.resolve(); - } - if (repository != null && enableQueryDef != null) { + + RepositoryDef repositoryDef = getRepositoryDef(); + Class[] queries = repositoryDef.getQueries(); + + this.mergedRepositoryResolver = new MergedRepositoryResolver(this); + this.mergedRepositoryResolver.resolve(); + if (queries != null && queries.length > 0) { this.queryTypeResolver = new QueryTypeResolver(this); - queryTypeResolver.resolve(); - this.stepwiseQueryExecutor = new StepwiseQueryExecutor(this); + this.queryTypeResolver.resolve(); } + + Map queryHandlerMap = new LinkedHashMap<>(4 * 4 / 3 + 1); + registryQueryHandlers(queryHandlerMap); + QueryHandler queryHandler = new AdaptiveQueryHandler(queryHandlerMap); + queryHandler = new SimpleQueryHandler(queryHandler); + queryHandler = new ContextMatchQueryHandler(this, queryHandler); + queryHandler = new ExampleQueryHandler(this, queryHandler); + this.queryHandler = queryHandler; + } + + protected void registryQueryHandlers(Map queryHandlerMap) { + queryHandlerMap.put(QueryMethod.STEPWISE, new StepwiseQueryHandler(this, null)); } @Override @SuppressWarnings("unchecked") public List selectByQuery(Options options, Object query) { - QueryContext queryContext = new QueryContext((Context) options, query, ResultType.DATA); - Result result = executeQuery(queryContext); - return (List) result.getRecords(); + QueryContext queryContext = new QueryContext((Context) options, query.getClass(), ResultType.DATA); + queryHandler.handle(queryContext, query); + + Context context = queryContext.getContext(); + Example example = queryContext.getExample(); + Result result = queryContext.getResult(); + + if (queryContext.isAbandoned()) { + return Collections.emptyList(); + } + if (result != null) { + return (List) result.getRecords(); + } + return selectByExample(context, example); } @Override @SuppressWarnings("unchecked") public Page selectPageByQuery(Options options, Object query) { - QueryContext queryContext = new QueryContext((Context) options, query, ResultType.COUNT_AND_DATA); - Result result = executeQuery(queryContext); - return (Page) result.getPage(); + QueryContext queryContext = new QueryContext((Context) options, query.getClass(), ResultType.COUNT_AND_DATA); + queryHandler.handle(queryContext, query); + + Context context = queryContext.getContext(); + Example example = queryContext.getExample(); + Result result = queryContext.getResult(); + + if (queryContext.isAbandoned()) { + return (Page) example.getPage(); + } + if (result != null) { + return (Page) result.getPage(); + } + return selectPageByExample(context, example); } @Override public long selectCountByQuery(Options options, Object query) { - QueryContext queryContext = new QueryContext((Context) options, query, ResultType.COUNT); - Result result = executeQuery(queryContext); - return result.getCount(); - } + QueryContext queryContext = new QueryContext((Context) options, query.getClass(), ResultType.COUNT); + queryHandler.handle(queryContext, query); - @Override - public Result executeQuery(QueryContext queryContext) { - QueryExecutor queryExecutor = adaptiveQueryExecutor(queryContext); - return queryExecutor.executeQuery(queryContext); - } + Context context = queryContext.getContext(); + Example example = queryContext.getExample(); + Result result = queryContext.getResult(); - protected QueryExecutor adaptiveQueryExecutor(QueryContext queryContext) { - return stepwiseQueryExecutor; + if (queryContext.isAbandoned()) { + return 0L; + } + if (result != null) { + return result.getCount(); + } + return selectCountByExample(context, example); } } diff --git a/dorive-ref/pom.xml b/dorive-ref/pom.xml index ceb8a27586ef9ed54dcdfd90d63e8ebc38d2f0b7..f0777915d9cff59d55c5d7103b5a872eb8902860 100644 --- a/dorive-ref/pom.xml +++ b/dorive-ref/pom.xml @@ -6,7 +6,7 @@ com.gitee.digital-engine dorive - 3.5.0.3 + 3.5.0.4 dorive-ref diff --git a/dorive-spring-boot-starter/pom.xml b/dorive-spring-boot-starter/pom.xml index 17fd99179e226b06f0d4db8cdd8da921699e7ff7..13a06129abb1d4c21a15c797195ca0e2a59051df 100644 --- a/dorive-spring-boot-starter/pom.xml +++ b/dorive-spring-boot-starter/pom.xml @@ -6,7 +6,7 @@ com.gitee.digital-engine dorive - 3.5.0.3 + 3.5.0.4 dorive-spring-boot-starter @@ -20,10 +20,5 @@ dorive-web ${project.version} - - com.gitee.digital-engine - dorive-mybatis-plus - ${project.version} - \ No newline at end of file diff --git a/dorive-sql/pom.xml b/dorive-sql/pom.xml index 3ad8e736246cd967f1d6a78fb5009604af885980..fed9ee878e719b49661072c7393400662d517844 100644 --- a/dorive-sql/pom.xml +++ b/dorive-sql/pom.xml @@ -6,7 +6,7 @@ com.gitee.digital-engine dorive - 3.5.0.3 + 3.5.0.4 dorive-sql diff --git a/dorive-sql/src/main/java/com/gitee/dorive/sql/impl/handler/SqlBuildQueryHandler.java b/dorive-sql/src/main/java/com/gitee/dorive/sql/impl/handler/SqlBuildQueryHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..d3553f8d6ac17272c05df25f1b7d10de2fd559bf --- /dev/null +++ b/dorive-sql/src/main/java/com/gitee/dorive/sql/impl/handler/SqlBuildQueryHandler.java @@ -0,0 +1,45 @@ +/* + * 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.handler; + +import com.gitee.dorive.core.entity.executor.Example; +import com.gitee.dorive.query.api.QueryHandler; +import com.gitee.dorive.query.entity.MergedRepository; +import com.gitee.dorive.query.entity.QueryContext; +import com.gitee.dorive.query.entity.QueryUnit; +import com.gitee.dorive.query.impl.handler.QueryUnitQueryHandler; +import com.gitee.dorive.query.repository.AbstractQueryRepository; +import com.gitee.dorive.sql.impl.segment.SegmentUnitResolver; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class SqlBuildQueryHandler extends QueryUnitQueryHandler { + + public SqlBuildQueryHandler(AbstractQueryRepository repository, QueryHandler queryHandler) { + super(repository, queryHandler); + } + + @Override + protected QueryUnit newQueryUnit(QueryContext queryContext, MergedRepository mergedRepository, Example example) { + SegmentUnitResolver segmentUnitResolver = new SegmentUnitResolver(repository, queryContext, mergedRepository, example); + return segmentUnitResolver.resolve(); + } + +} diff --git a/dorive-sql/src/main/java/com/gitee/dorive/sql/impl/executor/SqlQueryExecutor.java b/dorive-sql/src/main/java/com/gitee/dorive/sql/impl/handler/SqlExecuteQueryHandler.java similarity index 69% rename from dorive-sql/src/main/java/com/gitee/dorive/sql/impl/executor/SqlQueryExecutor.java rename to dorive-sql/src/main/java/com/gitee/dorive/sql/impl/handler/SqlExecuteQueryHandler.java index 6c0f7edc34ad6291f6d7de0dd4b08f9cacb023f9..549d814d98f9474fa7790cdbf2327d8e15bf2cb9 100644 --- a/dorive-sql/src/main/java/com/gitee/dorive/sql/impl/executor/SqlQueryExecutor.java +++ b/dorive-sql/src/main/java/com/gitee/dorive/sql/impl/handler/SqlExecuteQueryHandler.java @@ -15,23 +15,23 @@ * limitations under the License. */ -package com.gitee.dorive.sql.impl.executor; +package com.gitee.dorive.sql.impl.handler; import cn.hutool.core.collection.CollUtil; -import com.gitee.dorive.core.api.context.Context; -import com.gitee.dorive.core.entity.executor.*; -import com.gitee.dorive.query.entity.MergedRepository; +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.query.api.QueryHandler; import com.gitee.dorive.query.entity.QueryContext; import com.gitee.dorive.query.entity.QueryUnit; 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.segment.ArgSegment; import com.gitee.dorive.sql.entity.segment.SelectSegment; import com.gitee.dorive.sql.entity.segment.TableSegment; import com.gitee.dorive.sql.impl.segment.SelectSegmentBuilder; -import com.gitee.dorive.sql.impl.segment.SegmentUnitResolver; import lombok.Getter; import lombok.Setter; @@ -41,31 +41,27 @@ import java.util.Map; @Getter @Setter -public class SqlQueryExecutor extends AbstractQueryExecutor { +public class SqlExecuteQueryHandler extends SqlBuildQueryHandler { - protected SqlRunner sqlRunner; + private final SqlRunner sqlRunner; - public SqlQueryExecutor(AbstractQueryRepository repository, SqlRunner sqlRunner) { - super(repository); + public SqlExecuteQueryHandler(AbstractQueryRepository repository, QueryHandler queryHandler, SqlRunner sqlRunner) { + super(repository, queryHandler); this.sqlRunner = sqlRunner; } @Override - protected QueryUnit newQueryUnit(QueryContext queryContext, MergedRepository mergedRepository, Example example) { - SegmentUnitResolver segmentUnitResolver = new SegmentUnitResolver(repository, queryContext, mergedRepository, example); - return segmentUnitResolver.resolve(); + public void handle(QueryContext queryContext, Object query) { + super.handle(queryContext, query); + doHandle(queryContext); } - @Override - @SuppressWarnings("unchecked") - public Result doExecuteQuery(QueryContext queryContext) { - Context context = queryContext.getContext(); + protected void doHandle(QueryContext queryContext) { ResultType resultType = queryContext.getResultType(); Example example = queryContext.getExample(); QueryUnit queryUnit = queryContext.getQueryUnit(); boolean needCount = queryContext.isNeedCount(); - Result emptyResult = queryContext.newEmptyResult(); OrderBy orderBy = example.getOrderBy(); Page page = example.getPage(); @@ -81,7 +77,7 @@ public class SqlQueryExecutor extends AbstractQueryExecutor { List args = selectSegment.getArgs(); if (!tableSegment.isJoin() || argSegments.isEmpty()) { - return super.executeRootQuery(queryContext); + return; } String tableAlias = tableSegment.getTableAlias(); @@ -97,10 +93,12 @@ public class SqlQueryExecutor extends AbstractQueryExecutor { String countSql = selectSql + fromWhereSql; long count = sqlRunner.selectCount("SELECT COUNT(*) AS total FROM (" + countSql + ") c", args.toArray()); if (count == 0L) { - return emptyResult; + queryUnit.setAbandoned(true); + return; } if (resultType == ResultType.COUNT) { - return new Result<>(count); + queryContext.setResult(new Result<>(count)); + return; } if (page != null) { page.setTotal(count); @@ -124,20 +122,15 @@ public class SqlQueryExecutor extends AbstractQueryExecutor { selectSegment.setLimit(page.toString()); } + // 查询主键 String sql = selectSql + fromWhereSql + selectSegment.lastSql(); List> resultMaps = sqlRunner.selectList(sql, args.toArray()); - List primaryKeys = CollUtil.map(resultMaps, map -> map.get(primaryKeyAlias), true); - if (!primaryKeys.isEmpty()) { - Example newExample = new InnerExample().in(primaryKey, primaryKeys); - List entities = (List) repository.selectByExample(context, newExample); - if (page != null) { - page.setRecords(entities); - return new Result<>(page); - } else { - return new Result<>(entities); - } + List ids = CollUtil.map(resultMaps, map -> map.get(primaryKeyAlias), true); + if (!ids.isEmpty()) { + example.in(primaryKey, ids); + } else { + queryContext.setAbandoned(true); } - return emptyResult; } } diff --git a/dorive-sql/src/main/java/com/gitee/dorive/sql/impl/executor/CountSqlQueryExecutor.java b/dorive-sql/src/main/java/com/gitee/dorive/sql/impl/querier/SqlCountQuerier.java similarity index 87% rename from dorive-sql/src/main/java/com/gitee/dorive/sql/impl/executor/CountSqlQueryExecutor.java rename to dorive-sql/src/main/java/com/gitee/dorive/sql/impl/querier/SqlCountQuerier.java index 9641535b2f3ad84468da26be92012b4e025a2f92..e402fa5cb44f1517217b8461ee0837b98bf671a2 100644 --- a/dorive-sql/src/main/java/com/gitee/dorive/sql/impl/executor/CountSqlQueryExecutor.java +++ b/dorive-sql/src/main/java/com/gitee/dorive/sql/impl/querier/SqlCountQuerier.java @@ -15,12 +15,14 @@ * limitations under the License. */ -package com.gitee.dorive.sql.impl.executor; +package com.gitee.dorive.sql.impl.querier; import cn.hutool.core.collection.CollUtil; import com.gitee.dorive.api.entity.core.EntityElement; import com.gitee.dorive.core.api.context.Context; +import com.gitee.dorive.query.api.QueryHandler; import com.gitee.dorive.query.entity.QueryContext; +import com.gitee.dorive.query.entity.enums.QueryMethod; import com.gitee.dorive.query.entity.enums.ResultType; import com.gitee.dorive.query.repository.AbstractQueryRepository; import com.gitee.dorive.sql.api.CountQuerier; @@ -29,6 +31,7 @@ import com.gitee.dorive.sql.entity.common.CountQuery; import com.gitee.dorive.sql.entity.common.SegmentUnit; import com.gitee.dorive.sql.entity.segment.SelectSegment; import com.gitee.dorive.sql.impl.segment.SelectSegmentBuilder; +import lombok.AllArgsConstructor; import lombok.Getter; import lombok.Setter; @@ -39,16 +42,21 @@ import java.util.Map; @Getter @Setter -public class CountSqlQueryExecutor extends SqlQueryExecutor implements CountQuerier { +@AllArgsConstructor +public class SqlCountQuerier implements CountQuerier { - public CountSqlQueryExecutor(AbstractQueryRepository repository, SqlRunner sqlRunner) { - super(repository, sqlRunner); - } + private final AbstractQueryRepository repository; + private final QueryHandler queryHandler; + private final SqlRunner sqlRunner; @Override public Map selectCountMap(Context context, CountQuery countQuery) { - QueryContext queryContext = new QueryContext(context, countQuery.getQuery(), ResultType.COUNT); - resolve(queryContext); + Object query = countQuery.getQuery(); + QueryContext queryContext = new QueryContext(context, query.getClass(), ResultType.COUNT); + + queryContext.setOption(QueryMethod.class, QueryMethod.SQL_BUILD); + queryHandler.handle(queryContext, query); + SegmentUnit segmentUnit = (SegmentUnit) queryContext.getQueryUnit(); EntityElement entityElement = segmentUnit.getEntityElement(); String tableAlias = segmentUnit.getTableAlias(); diff --git a/dorive-web/pom.xml b/dorive-web/pom.xml index a9c268ea4d691f88475b920e5a6efe3a387efde8..54d1281bb75170b0f838531423522964201cd62f 100644 --- a/dorive-web/pom.xml +++ b/dorive-web/pom.xml @@ -6,25 +6,22 @@ com.gitee.digital-engine dorive - 3.5.0.3 + 3.5.0.4 dorive-web - org.springframework.boot - spring-boot-starter-web - - - org.projectlombok - lombok + com.gitee.digital-engine + dorive-mybatis-plus + ${project.version} - org.apache.commons - commons-lang3 + org.springframework.boot + spring-boot-starter-web - cn.hutool - hutool-all + org.springframework.boot + spring-boot-starter-aop \ No newline at end of file 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 index 5ec57b8aa619a4c56a1659c648e34529a9d3c1a3..0421e0fe8dcc85f3bf798fc4b9a58a8f1c5108cf 100644 --- 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 @@ -17,7 +17,11 @@ package com.gitee.dorive.web.config; -import com.gitee.dorive.web.advice.ParameterControllerAdvice; +import com.gitee.dorive.web.impl.DomainController; +import com.gitee.dorive.web.impl.DomainService; +import com.gitee.dorive.web.impl.advice.ParameterControllerAdvice; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.Order; @@ -31,4 +35,16 @@ public class DoriveWebConfiguration { return new ParameterControllerAdvice(); } + @Bean("domainService") + @ConditionalOnProperty(name = "dorive.web.enable", havingValue = "true", matchIfMissing = true) + public static DomainService domainService(ApplicationContext applicationContext) { + return new DomainService(applicationContext); + } + + @Bean("domainController") + @ConditionalOnProperty(name = "dorive.web.enable", havingValue = "true", matchIfMissing = true) + public static DomainController domainController(DomainService domainService) { + return new DomainController(domainService); + } + } diff --git a/dorive-event/src/main/java/com/gitee/dorive/event/config/DoriveEventConfiguration.java b/dorive-web/src/main/java/com/gitee/dorive/web/entity/ExporterConfig.java similarity index 62% rename from dorive-event/src/main/java/com/gitee/dorive/event/config/DoriveEventConfiguration.java rename to dorive-web/src/main/java/com/gitee/dorive/web/entity/ExporterConfig.java index b9cfc849baffc29ffe0bca4830bf41cd5ecdf8e2..6a3d3e614e3d9ef4936a68501ca126aa5df5a58f 100644 --- a/dorive-event/src/main/java/com/gitee/dorive/event/config/DoriveEventConfiguration.java +++ b/dorive-web/src/main/java/com/gitee/dorive/web/entity/ExporterConfig.java @@ -15,20 +15,21 @@ * limitations under the License. */ -package com.gitee.dorive.event.config; +package com.gitee.dorive.web.entity; -import com.gitee.dorive.event.impl.listener.EventListener; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.core.annotation.Order; +import com.gitee.dorive.core.api.context.Selector; +import com.gitee.dorive.query.repository.AbstractQueryRepository; +import lombok.Data; -@Order(-100) -@Configuration -public class DoriveEventConfiguration { - - @Bean("eventListenerV3") - public EventListener eventListener() { - return new EventListener(); - } +import java.util.List; +import java.util.Map; +@Data +public class ExporterConfig { + private String url; + private Class entityClass; + private Selector selector; + private AbstractQueryRepository repository; + private Class queryClass; + private Map> filterIdPropertiesMap; } diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/api/executor/EntityJoiner.java b/dorive-web/src/main/java/com/gitee/dorive/web/entity/req/ListOrPageReq.java similarity index 65% rename from dorive-core/src/main/java/com/gitee/dorive/core/api/executor/EntityJoiner.java rename to dorive-web/src/main/java/com/gitee/dorive/web/entity/req/ListOrPageReq.java index 132a3f48297b40e99e9d38b3a1545d36f262bc68..219c86740540351d08bb949cd61f2a7e52038ad3 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/api/executor/EntityJoiner.java +++ b/dorive-web/src/main/java/com/gitee/dorive/web/entity/req/ListOrPageReq.java @@ -15,18 +15,20 @@ * limitations under the License. */ -package com.gitee.dorive.core.api.executor; +package com.gitee.dorive.web.entity.req; -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 lombok.Data; -import java.util.List; - -public interface EntityJoiner { - - Example newExample(Context context, List entities); - - void join(Context context, List entities, Result result); +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.Map; +@Data +public class ListOrPageReq { + private HttpServletRequest request; + private HttpServletResponse response; + private String methodName; + private String entity; + private String config; + private Map params; } diff --git a/dorive-web/src/main/java/com/gitee/dorive/web/entity/req/LoadConfigReq.java b/dorive-web/src/main/java/com/gitee/dorive/web/entity/req/LoadConfigReq.java new file mode 100644 index 0000000000000000000000000000000000000000..b068b4e36a19fc9ef0ae03ed47ee4343d5c8a597 --- /dev/null +++ b/dorive-web/src/main/java/com/gitee/dorive/web/entity/req/LoadConfigReq.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.web.entity.req; + +import lombok.Data; + +@Data +public class LoadConfigReq { + private String url; + private String entityType; + private String selectorName; + private String repositoryType; + private String queryType; +} diff --git a/dorive-web/src/main/java/com/gitee/dorive/web/impl/DomainController.java b/dorive-web/src/main/java/com/gitee/dorive/web/impl/DomainController.java new file mode 100644 index 0000000000000000000000000000000000000000..aad0b3c39dc8eb67e3f9b4265a7b37ec126ea92c --- /dev/null +++ b/dorive-web/src/main/java/com/gitee/dorive/web/impl/DomainController.java @@ -0,0 +1,71 @@ +/* + * 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.impl; + +import com.gitee.dorive.web.entity.ResObject; +import com.gitee.dorive.web.entity.req.ListOrPageReq; +import com.gitee.dorive.web.entity.req.LoadConfigReq; +import lombok.AllArgsConstructor; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.List; +import java.util.Map; + +@RestController +@AllArgsConstructor +@RequestMapping("/domain") +public class DomainController { + + private final DomainService domainService; + + @PostMapping("/loadConfigs") + public ResObject loadConfigs(@RequestBody List loadConfigReqs) { + return domainService.loadConfigs(loadConfigReqs); + } + + @GetMapping("/list/{entity}/{config}") + public void list(HttpServletRequest request, HttpServletResponse response, + @PathVariable String entity, @PathVariable String config, + @RequestParam Map params) throws Exception { + executeQuery(request, response, "list", entity, config, params); + } + + @GetMapping("/page/{entity}/{config}") + public void page(HttpServletRequest request, HttpServletResponse response, + @PathVariable String entity, @PathVariable String config, + @RequestParam Map params) throws Exception { + executeQuery(request, response, "page", entity, config, params); + } + + private void executeQuery(HttpServletRequest request, HttpServletResponse response, + String methodName, String entity, String config, + Map params) throws IOException { + ListOrPageReq listOrPageReq = new ListOrPageReq(); + listOrPageReq.setRequest(request); + listOrPageReq.setResponse(response); + listOrPageReq.setMethodName(methodName); + listOrPageReq.setEntity(entity); + listOrPageReq.setConfig(config); + listOrPageReq.setParams(params); + domainService.executeQuery(listOrPageReq); + } + +} diff --git a/dorive-web/src/main/java/com/gitee/dorive/web/impl/DomainService.java b/dorive-web/src/main/java/com/gitee/dorive/web/impl/DomainService.java new file mode 100644 index 0000000000000000000000000000000000000000..b4e7f99ef6bbcb3f1e5c3119bf983e44ab88ed5d --- /dev/null +++ b/dorive-web/src/main/java/com/gitee/dorive/web/impl/DomainService.java @@ -0,0 +1,227 @@ +/* + * 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.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.util.ClassLoaderUtil; +import cn.hutool.core.util.ReflectUtil; +import cn.hutool.http.ContentType; +import cn.hutool.json.JSONUtil; +import com.fasterxml.jackson.databind.BeanDescription; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationConfig; +import com.fasterxml.jackson.databind.ser.BeanSerializerFactory; +import com.fasterxml.jackson.databind.ser.PropertyFilter; +import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter; +import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider; +import com.gitee.dorive.api.annotation.core.Entity; +import com.gitee.dorive.api.entity.core.EntityElement; +import com.gitee.dorive.core.api.context.Selector; +import com.gitee.dorive.core.entity.executor.Page; +import com.gitee.dorive.core.repository.CommonRepository; +import com.gitee.dorive.query.entity.MergedRepository; +import com.gitee.dorive.query.impl.resolver.MergedRepositoryResolver; +import com.gitee.dorive.query.repository.AbstractQueryRepository; +import com.gitee.dorive.web.entity.ExporterConfig; +import com.gitee.dorive.web.entity.ResObject; +import com.gitee.dorive.web.entity.req.ListOrPageReq; +import com.gitee.dorive.web.entity.req.LoadConfigReq; +import org.springframework.context.ApplicationContext; +import org.springframework.http.HttpHeaders; +import org.springframework.stereotype.Service; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; + +@Service +public class DomainService { + + private final ApplicationContext applicationContext; + private final Map urlExporterConfigMap; + + public DomainService(ApplicationContext applicationContext) { + this.applicationContext = applicationContext; + this.urlExporterConfigMap = new ConcurrentHashMap<>(); + } + + public ResObject loadConfigs(List loadConfigReqs) { + for (LoadConfigReq loadConfigReq : loadConfigReqs) { + ResObject resObject = loadConfig(loadConfigReq); + if (resObject.isFail()) { + return resObject; + } + } + return ResObject.successMsg("加载成功!"); + } + + private ResObject loadConfig(LoadConfigReq loadConfigReq) { + String url = loadConfigReq.getUrl(); + String entityType = loadConfigReq.getEntityType(); + String selectorName = loadConfigReq.getSelectorName(); + String repositoryType = loadConfigReq.getRepositoryType(); + String queryType = loadConfigReq.getQueryType(); + + Class entityClass = ClassLoaderUtil.loadClass(entityType); + Class repositoryClass = ClassLoaderUtil.loadClass(repositoryType); + Class queryClass = ClassLoaderUtil.loadClass(queryType); + + AbstractQueryRepository repository = (AbstractQueryRepository) applicationContext.getBean(repositoryClass); + MergedRepositoryResolver mergedRepositoryResolver = repository.getMergedRepositoryResolver(); + Map nameMergedRepositoryMap = mergedRepositoryResolver.getNameMergedRepositoryMap(); + + Field staticField = ReflectUtil.getField(entityClass, selectorName); + Object value = ReflectUtil.getStaticFieldValue(staticField); + Selector selector = (Selector) value; + + Map> filterIdPropertiesMap = new LinkedHashMap<>(8); + Set names = selector.getNames(); + for (String entityName : names) { + MergedRepository mergedRepository = nameMergedRepositoryMap.get(entityName); + CommonRepository definedRepository = mergedRepository.getDefinedRepository(); + EntityElement entityElement = definedRepository.getEntityElement(); + Class genericType = entityElement.getGenericType(); + String filterId = genericType.getName(); + List properties = filterIdPropertiesMap.computeIfAbsent(filterId, key -> new ArrayList<>(4)); + List select = selector.select(entityName); + if (select == null || select.isEmpty()) { + Field[] fields = ReflectUtil.getFieldsDirectly(genericType, true); + for (Field field : fields) { + if (!Modifier.isStatic(field.getModifiers())) { + properties.add(field.getName()); + } + } + } else { + properties.addAll(select); + } + + // 补充内部实体的字段 + Field field = entityElement.getJavaField(); + if (field != null) { + Class declaringClass = field.getDeclaringClass(); + String declaringFilterId = declaringClass.getName(); + List declaringProperties = filterIdPropertiesMap.computeIfAbsent(declaringFilterId, key -> new ArrayList<>(4)); + declaringProperties.add(field.getName()); + } + } + + ExporterConfig exporterConfig = new ExporterConfig(); + exporterConfig.setUrl(url); + exporterConfig.setEntityClass(entityClass); + exporterConfig.setSelector(selector); + exporterConfig.setRepository(repository); + exporterConfig.setQueryClass(queryClass); + exporterConfig.setFilterIdPropertiesMap(filterIdPropertiesMap); + urlExporterConfigMap.put(url, exporterConfig); + + return ResObject.successMsg("加载成功!"); + } + + public void executeQuery(ListOrPageReq listOrPageReq) throws IOException { + HttpServletResponse response = listOrPageReq.getResponse(); + String methodName = listOrPageReq.getMethodName(); + String entity = listOrPageReq.getEntity(); + String config = listOrPageReq.getConfig(); + Map params = listOrPageReq.getParams(); + + response.setHeader(HttpHeaders.CONTENT_TYPE, ContentType.JSON.getValue()); + + ExporterConfig exporterConfig = urlExporterConfigMap.get(entity + "/" + config); + if (exporterConfig == null) { + failMsg(response, "没有找到配置信息!"); + return; + } + + AbstractQueryRepository repository = exporterConfig.getRepository(); + Selector selector = exporterConfig.getSelector(); + Object query = BeanUtil.toBean(params, exporterConfig.getQueryClass()); + Object data = null; + try { + if ("list".equals(methodName)) { + List entities = repository.selectByQuery(selector, query); + data = ResObject.successData(entities); + + } else if ("page".equals(methodName)) { + Page page = repository.selectPageByQuery(selector, query); + data = ResObject.successData(page); + } + + } catch (Exception e) { + failMsg(response, e.getMessage()); + return; + } + + ObjectMapper objectMapper = new ObjectMapper(); + addFilters(objectMapper, exporterConfig.getFilterIdPropertiesMap()); + objectMapper.writeValue(response.getOutputStream(), data); + } + + private void failMsg(HttpServletResponse response, String message) throws IOException { + ResObject resObject = ResObject.failMsg(message); + response.getWriter().write(JSONUtil.toJsonStr(resObject)); + } + + private void addFilters(ObjectMapper objectMapper, Map> filterIdPropertiesMap) { + objectMapper.setSerializerFactory(FilterBeanSerializerFactory.instance); + SimpleFilterProvider simpleFilterProvider = new SuperclassFilterProvider(); + filterIdPropertiesMap.forEach((filterId, properties) -> + simpleFilterProvider.addFilter(filterId, SimpleBeanPropertyFilter.filterOutAllExcept(properties.toArray(new String[0])))); + objectMapper.setFilterProvider(simpleFilterProvider); + } + + public static class FilterBeanSerializerFactory extends BeanSerializerFactory { + public static FilterBeanSerializerFactory instance = new FilterBeanSerializerFactory(); + + protected FilterBeanSerializerFactory() { + super(null); + } + + @Override + protected Object findFilterId(SerializationConfig config, BeanDescription beanDesc) { + Class beanClass = beanDesc.getBeanClass(); + if (beanClass.isAnnotationPresent(Entity.class)) { + return beanClass.getName(); + } + return super.findFilterId(config, beanDesc); + } + } + + public static class SuperclassFilterProvider extends SimpleFilterProvider { + @Override + public PropertyFilter findPropertyFilter(Object filterId, Object valueToFilter) { + String key = (String) filterId; + PropertyFilter propertyFilter; + while (true) { + propertyFilter = _filtersById.get(key); + if (propertyFilter != null) { + break; + } + Class superclass = valueToFilter.getClass().getSuperclass(); + if (superclass == null || superclass == Object.class) { + break; + } + key = superclass.getName(); + } + return propertyFilter != null ? propertyFilter : super.findPropertyFilter(filterId, valueToFilter); + } + } + +} 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/impl/advice/ParameterControllerAdvice.java similarity index 98% rename from dorive-web/src/main/java/com/gitee/dorive/web/advice/ParameterControllerAdvice.java rename to dorive-web/src/main/java/com/gitee/dorive/web/impl/advice/ParameterControllerAdvice.java index 4720d25569520708686edea94c22d7780a6b97c1..1a01888ca341b747698fd17cf920c83d52459426 100644 --- a/dorive-web/src/main/java/com/gitee/dorive/web/advice/ParameterControllerAdvice.java +++ b/dorive-web/src/main/java/com/gitee/dorive/web/impl/advice/ParameterControllerAdvice.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package com.gitee.dorive.web.advice; +package com.gitee.dorive.web.impl.advice; import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.NumberUtil; diff --git a/pom.xml b/pom.xml index 2cdd11d8aa15adb0ad679411f993db2fead90552..6f45b8729d42fd2d0b6f1d3e7d22d241ccbc529e 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ 4.0.0 com.gitee.digital-engine dorive - 3.5.0.3 + 3.5.0.4 pom @@ -31,7 +31,6 @@ dorive-inject dorive-env - dorive-web dorive-api dorive-core dorive-event @@ -39,6 +38,7 @@ dorive-ref dorive-sql dorive-mybatis-plus + dorive-web dorive-spring-boot-starter @@ -61,6 +61,11 @@ spring-boot-starter-web 2.7.18 + + org.springframework.boot + spring-boot-starter-aop + 2.7.18 + org.springframework spring-tx