From b15867d72211135fccb1d12b5ab49a9eb27e6c70 Mon Sep 17 00:00:00 2001 From: chentaoah <609580885@qq.com> Date: Sat, 15 Apr 2023 14:00:32 +0800 Subject: [PATCH 1/9] =?UTF-8?q?=E5=8D=87=E7=BA=A7=E7=89=88=E6=9C=AC?= =?UTF-8?q?=E8=87=B33.3.2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dorive-api/pom.xml | 2 +- dorive-coating/pom.xml | 2 +- dorive-core/pom.xml | 2 +- dorive-event/pom.xml | 2 +- dorive-injection/pom.xml | 2 +- dorive-proxy/pom.xml | 2 +- dorive-ref/pom.xml | 2 +- dorive-spring-boot-starter/pom.xml | 2 +- dorive-web/pom.xml | 2 +- pom.xml | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/dorive-api/pom.xml b/dorive-api/pom.xml index d3b0921a..d052941b 100644 --- a/dorive-api/pom.xml +++ b/dorive-api/pom.xml @@ -6,7 +6,7 @@ com.gitee.digital-engine dorive - 3.3.1 + 3.3.2 dorive-api diff --git a/dorive-coating/pom.xml b/dorive-coating/pom.xml index f5d2f1d1..4ced627d 100644 --- a/dorive-coating/pom.xml +++ b/dorive-coating/pom.xml @@ -6,7 +6,7 @@ com.gitee.digital-engine dorive - 3.3.1 + 3.3.2 dorive-coating diff --git a/dorive-core/pom.xml b/dorive-core/pom.xml index d8250c03..f3692fe0 100644 --- a/dorive-core/pom.xml +++ b/dorive-core/pom.xml @@ -6,7 +6,7 @@ com.gitee.digital-engine dorive - 3.3.1 + 3.3.2 dorive-core diff --git a/dorive-event/pom.xml b/dorive-event/pom.xml index 7f9ef0e4..d21af2c5 100644 --- a/dorive-event/pom.xml +++ b/dorive-event/pom.xml @@ -6,7 +6,7 @@ com.gitee.digital-engine dorive - 3.3.1 + 3.3.2 dorive-event diff --git a/dorive-injection/pom.xml b/dorive-injection/pom.xml index 4c55ed65..cc244a34 100644 --- a/dorive-injection/pom.xml +++ b/dorive-injection/pom.xml @@ -6,7 +6,7 @@ com.gitee.digital-engine dorive - 3.3.1 + 3.3.2 dorive-injection diff --git a/dorive-proxy/pom.xml b/dorive-proxy/pom.xml index 602337c8..1dd33e7b 100644 --- a/dorive-proxy/pom.xml +++ b/dorive-proxy/pom.xml @@ -6,7 +6,7 @@ com.gitee.digital-engine dorive - 3.3.1 + 3.3.2 dorive-proxy diff --git a/dorive-ref/pom.xml b/dorive-ref/pom.xml index abc79fe4..59abf3a0 100644 --- a/dorive-ref/pom.xml +++ b/dorive-ref/pom.xml @@ -6,7 +6,7 @@ com.gitee.digital-engine dorive - 3.3.1 + 3.3.2 dorive-ref diff --git a/dorive-spring-boot-starter/pom.xml b/dorive-spring-boot-starter/pom.xml index 1d941b6e..43d6bcbb 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.3.1 + 3.3.2 dorive-spring-boot-starter diff --git a/dorive-web/pom.xml b/dorive-web/pom.xml index 1a0151b8..4212f158 100644 --- a/dorive-web/pom.xml +++ b/dorive-web/pom.xml @@ -6,7 +6,7 @@ com.gitee.digital-engine dorive - 3.3.1 + 3.3.2 dorive-web diff --git a/pom.xml b/pom.xml index 87fff6ba..ac09b773 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ 4.0.0 com.gitee.digital-engine dorive - 3.3.1 + 3.3.2 pom -- Gitee From 992109e72e868828e01d7ee8439bf15f70d5dc31 Mon Sep 17 00:00:00 2001 From: chentaoah <609580885@qq.com> Date: Sat, 15 Apr 2023 14:30:15 +0800 Subject: [PATCH 2/9] =?UTF-8?q?=E7=A7=BB=E9=99=A4web=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dorive-api/pom.xml | 2 +- dorive-injection/pom.xml | 2 +- dorive-spring-boot-starter/pom.xml | 2 +- dorive-web/pom.xml | 19 ---- .../com/gitee/dorive/web/api/RestService.java | 37 ------- .../gitee/dorive/web/common/ResObject.java | 66 ------------- .../dorive/web/impl/AbstractController.java | 85 ---------------- .../dorive/web/impl/AbstractService.java | 98 ------------------- pom.xml | 3 +- 9 files changed, 4 insertions(+), 310 deletions(-) delete mode 100644 dorive-web/pom.xml delete mode 100644 dorive-web/src/main/java/com/gitee/dorive/web/api/RestService.java delete mode 100644 dorive-web/src/main/java/com/gitee/dorive/web/common/ResObject.java delete mode 100644 dorive-web/src/main/java/com/gitee/dorive/web/impl/AbstractController.java delete mode 100644 dorive-web/src/main/java/com/gitee/dorive/web/impl/AbstractService.java diff --git a/dorive-api/pom.xml b/dorive-api/pom.xml index d052941b..9fe8d72b 100644 --- a/dorive-api/pom.xml +++ b/dorive-api/pom.xml @@ -17,7 +17,7 @@ org.springframework.boot - spring-boot-starter-web + spring-boot-starter org.projectlombok diff --git a/dorive-injection/pom.xml b/dorive-injection/pom.xml index cc244a34..0652a57e 100644 --- a/dorive-injection/pom.xml +++ b/dorive-injection/pom.xml @@ -12,7 +12,7 @@ org.springframework.boot - spring-boot-starter-web + spring-boot-starter org.projectlombok diff --git a/dorive-spring-boot-starter/pom.xml b/dorive-spring-boot-starter/pom.xml index 43d6bcbb..57015d37 100644 --- a/dorive-spring-boot-starter/pom.xml +++ b/dorive-spring-boot-starter/pom.xml @@ -17,7 +17,7 @@ com.gitee.digital-engine - dorive-web + dorive-ref ${project.version} diff --git a/dorive-web/pom.xml b/dorive-web/pom.xml deleted file mode 100644 index 4212f158..00000000 --- a/dorive-web/pom.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - 4.0.0 - - com.gitee.digital-engine - dorive - 3.3.2 - - dorive-web - - - com.gitee.digital-engine - dorive-ref - ${project.version} - - - \ No newline at end of file diff --git a/dorive-web/src/main/java/com/gitee/dorive/web/api/RestService.java b/dorive-web/src/main/java/com/gitee/dorive/web/api/RestService.java deleted file mode 100644 index fe30eb72..00000000 --- a/dorive-web/src/main/java/com/gitee/dorive/web/api/RestService.java +++ /dev/null @@ -1,37 +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.web.api; - -import com.gitee.dorive.core.entity.executor.Page; -import com.gitee.dorive.web.common.ResObject; - -import java.util.List; - -public interface RestService { - - ResObject post(E entity); - - ResObject> get(Q query); - - ResObject> page(Q query); - - ResObject put(Integer id, E entity); - - ResObject delete(Integer id); - -} diff --git a/dorive-web/src/main/java/com/gitee/dorive/web/common/ResObject.java b/dorive-web/src/main/java/com/gitee/dorive/web/common/ResObject.java deleted file mode 100644 index d84395d5..00000000 --- a/dorive-web/src/main/java/com/gitee/dorive/web/common/ResObject.java +++ /dev/null @@ -1,66 +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.web.common; - -import com.fasterxml.jackson.annotation.JsonIgnore; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -@Data -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class ResObject { - - private int code; - private String message; - private T data; - - public static ResObject success() { - return new ResObject<>(0, "success", null); - } - - public static ResObject failure() { - return new ResObject<>(-1, "failed", null); - } - - public static ResObject successMsg(String message) { - return new ResObject<>(0, message, null); - } - - public static ResObject successData(T data) { - return new ResObject<>(0, "success", data); - } - - public static ResObject failMsg(String message) { - return new ResObject<>(-1, message, null); - } - - @JsonIgnore - public boolean isSuccess() { - return code == 0; - } - - @JsonIgnore - public boolean isFailed() { - return code == -1; - } - -} diff --git a/dorive-web/src/main/java/com/gitee/dorive/web/impl/AbstractController.java b/dorive-web/src/main/java/com/gitee/dorive/web/impl/AbstractController.java deleted file mode 100644 index 1cf484d9..00000000 --- a/dorive-web/src/main/java/com/gitee/dorive/web/impl/AbstractController.java +++ /dev/null @@ -1,85 +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.web.impl; - -import com.gitee.dorive.core.entity.executor.Page; -import com.gitee.dorive.api.util.ReflectUtils; -import com.gitee.dorive.web.api.RestService; -import com.gitee.dorive.web.common.ResObject; -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestBody; - -import java.util.List; - -public abstract class AbstractController, E, Q> - implements ApplicationContextAware, InitializingBean, RestService { - - protected ApplicationContext applicationContext; - protected S service; - - @Override - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - this.applicationContext = applicationContext; - } - - @Override - @SuppressWarnings("unchecked") - public void afterPropertiesSet() { - Class serviceType = ReflectUtils.getFirstArgumentType(this.getClass()); - this.service = (S) applicationContext.getBean(serviceType); - } - - @Override - @PostMapping - public ResObject post(@RequestBody E entity) { - return service.post(entity); - } - - @Override - @GetMapping - public ResObject> get(Q query) { - return service.get(query); - } - - @Override - @GetMapping("/page") - public ResObject> page(Q query) { - return service.page(query); - } - - @Override - @PutMapping("/{id}") - public ResObject put(@PathVariable Integer id, @RequestBody E entity) { - return service.put(id, entity); - } - - @Override - @DeleteMapping("/{id}") - public ResObject delete(@PathVariable Integer id) { - return service.delete(id); - } - -} diff --git a/dorive-web/src/main/java/com/gitee/dorive/web/impl/AbstractService.java b/dorive-web/src/main/java/com/gitee/dorive/web/impl/AbstractService.java deleted file mode 100644 index 0bb3524f..00000000 --- a/dorive-web/src/main/java/com/gitee/dorive/web/impl/AbstractService.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.gitee.dorive.web.impl; - -import com.gitee.dorive.api.entity.def.EntityDef; -import com.gitee.dorive.api.util.ReflectUtils; -import com.gitee.dorive.coating.repository.AbstractCoatingRepository; -import com.gitee.dorive.core.api.context.Context; -import com.gitee.dorive.core.api.context.Selector; -import com.gitee.dorive.core.entity.context.BoundedContext; -import com.gitee.dorive.core.entity.executor.Page; -import com.gitee.dorive.core.impl.selector.NameSelector; -import com.gitee.dorive.web.api.RestService; -import com.gitee.dorive.web.common.ResObject; -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; - -import java.util.List; - -public abstract class AbstractService, E, Q> - implements ApplicationContextAware, InitializingBean, RestService { - - protected ApplicationContext applicationContext; - protected R repository; - protected Selector selector; - - @Override - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - this.applicationContext = applicationContext; - } - - @Override - @SuppressWarnings("unchecked") - public void afterPropertiesSet() { - Class repositoryType = ReflectUtils.getFirstArgumentType(this.getClass()); - this.repository = (R) applicationContext.getBean(repositoryType); - EntityDef entityDef = repository.getEntityDef(); - String name = entityDef.getName(); - this.selector = new NameSelector(name); - } - - @Override - public ResObject post(E entity) { - Context context = newContext(entity, null); - int count = repository.insert(context, entity); - return count > 0 ? ResObject.success() : ResObject.failure(); - } - - @Override - public ResObject> get(Q query) { - Context context = newContext(null, query); - List entities = repository.selectByCoating(context, query); - return ResObject.successData(entities); - } - - @Override - public ResObject> page(Q query) { - Context context = newContext(null, query); - Page page = repository.selectPageByCoating(context, query); - return ResObject.successData(page); - } - - @Override - public ResObject put(Integer id, E entity) { - Context context = newContext(entity, null); - int count = repository.update(context, entity); - return count > 0 ? ResObject.success() : ResObject.failure(); - } - - @Override - public ResObject delete(Integer id) { - Context context = newContext(null, null); - int count = repository.deleteByPrimaryKey(context, id); - return count > 0 ? ResObject.success() : ResObject.failure(); - } - - protected Context newContext(E entity, Q query) { - return new BoundedContext(selector); - } - -} diff --git a/pom.xml b/pom.xml index ac09b773..39f7d1bc 100644 --- a/pom.xml +++ b/pom.xml @@ -36,7 +36,6 @@ dorive-event dorive-coating dorive-ref - dorive-web dorive-spring-boot-starter @@ -51,7 +50,7 @@ org.springframework.boot - spring-boot-starter-web + spring-boot-starter 2.7.8 -- Gitee From a4a48cd0037c354e46d0a3d56f14dc2b794ce44a Mon Sep 17 00:00:00 2001 From: chentaoah <609580885@qq.com> Date: Sat, 15 Apr 2023 15:57:26 +0800 Subject: [PATCH 3/9] =?UTF-8?q?=E7=A7=BB=E9=99=A4@Adapter?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gitee/dorive/api/annotation/Adapter.java | 43 ----------------- .../dorive/api/entity/def/AdapterDef.java | 46 ------------------- .../dorive/api/entity/element/EntityEle.java | 2 +- .../dorive/api/entity/element/EntityType.java | 3 -- .../impl/factory/DefaultEntityFactory.java | 8 ++-- .../repository/MybatisPlusRepository.java | 39 ++++++++-------- 6 files changed, 26 insertions(+), 115 deletions(-) delete mode 100644 dorive-api/src/main/java/com/gitee/dorive/api/annotation/Adapter.java delete mode 100644 dorive-api/src/main/java/com/gitee/dorive/api/entity/def/AdapterDef.java diff --git a/dorive-api/src/main/java/com/gitee/dorive/api/annotation/Adapter.java b/dorive-api/src/main/java/com/gitee/dorive/api/annotation/Adapter.java deleted file mode 100644 index be66fc66..00000000 --- a/dorive-api/src/main/java/com/gitee/dorive/api/annotation/Adapter.java +++ /dev/null @@ -1,43 +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; - -import org.springframework.core.annotation.AliasFor; - -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 Adapter { - - @AliasFor("adapter") - Class value() default Object.class; - - @AliasFor("value") - Class adapter() default Object.class; - - String[] args() default {}; - -} diff --git a/dorive-api/src/main/java/com/gitee/dorive/api/entity/def/AdapterDef.java b/dorive-api/src/main/java/com/gitee/dorive/api/entity/def/AdapterDef.java deleted file mode 100644 index 2a2de6ed..00000000 --- a/dorive-api/src/main/java/com/gitee/dorive/api/entity/def/AdapterDef.java +++ /dev/null @@ -1,46 +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.entity.def; - -import cn.hutool.core.bean.BeanUtil; -import com.gitee.dorive.api.annotation.Adapter; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import org.springframework.core.annotation.AnnotatedElementUtils; - -import java.lang.reflect.AnnotatedElement; -import java.util.Map; - -@Data -@NoArgsConstructor -@AllArgsConstructor -public class AdapterDef { - - private Class adapter; - private String[] args; - - public static AdapterDef fromElement(AnnotatedElement element) { - if (element.isAnnotationPresent(Adapter.class)) { - Map attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(element, Adapter.class); - return BeanUtil.copyProperties(attributes, AdapterDef.class); - } - return null; - } - -} diff --git a/dorive-api/src/main/java/com/gitee/dorive/api/entity/element/EntityEle.java b/dorive-api/src/main/java/com/gitee/dorive/api/entity/element/EntityEle.java index 0ad85b00..ffdb3ccf 100644 --- a/dorive-api/src/main/java/com/gitee/dorive/api/entity/element/EntityEle.java +++ b/dorive-api/src/main/java/com/gitee/dorive/api/entity/element/EntityEle.java @@ -89,7 +89,7 @@ public abstract class EntityEle { return properties; } - public Map newAliasPropMap() { + public Map newAliasFieldMapping() { Map map = new LinkedHashMap<>(); aliasMap.forEach((key, value) -> map.put(value, key)); return map; diff --git a/dorive-api/src/main/java/com/gitee/dorive/api/entity/element/EntityType.java b/dorive-api/src/main/java/com/gitee/dorive/api/entity/element/EntityType.java index 2a3355df..bc133a3b 100644 --- a/dorive-api/src/main/java/com/gitee/dorive/api/entity/element/EntityType.java +++ b/dorive-api/src/main/java/com/gitee/dorive/api/entity/element/EntityType.java @@ -22,7 +22,6 @@ import cn.hutool.core.lang.Assert; import cn.hutool.core.util.ReflectUtil; import cn.hutool.core.util.StrUtil; import com.gitee.dorive.api.api.PropProxy; -import com.gitee.dorive.api.entity.def.AdapterDef; import com.gitee.dorive.api.entity.def.AliasDef; import com.gitee.dorive.api.impl.factory.PropProxyFactory; import lombok.Data; @@ -44,7 +43,6 @@ public class EntityType extends EntityEle { private Class type; private String name; - private AdapterDef adapterDef; private Map entityFields = new LinkedHashMap<>(); public static synchronized EntityType getInstance(Class type) { @@ -63,7 +61,6 @@ public class EntityType extends EntityEle { this.type = type; this.name = type.getName(); - this.adapterDef = AdapterDef.fromElement(type); for (Field field : ReflectUtil.getFields(type)) { if (!Modifier.isStatic(field.getModifiers())) { EntityField entityField = new EntityField(field); diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/impl/factory/DefaultEntityFactory.java b/dorive-core/src/main/java/com/gitee/dorive/core/impl/factory/DefaultEntityFactory.java index bd205840..d65354f8 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/impl/factory/DefaultEntityFactory.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/impl/factory/DefaultEntityFactory.java @@ -35,18 +35,18 @@ public class DefaultEntityFactory implements EntityFactory { private EntityEle entityEle; private Class pojoClass; - private Map aliasPropMapping; - private Map propPojoMapping; + private Map aliasFieldMapping; + private Map fieldPropMapping; @Override public Object reconstitute(Context context, Object persistent) { - CopyOptions copyOptions = CopyOptions.create().ignoreNullValue().setFieldMapping(aliasPropMapping); + CopyOptions copyOptions = CopyOptions.create().ignoreNullValue().setFieldMapping(aliasFieldMapping); return BeanUtil.toBean(persistent, entityEle.getGenericType(), copyOptions); } @Override public Object deconstruct(Context context, Object entity) { - CopyOptions copyOptions = CopyOptions.create().ignoreNullValue().setFieldMapping(propPojoMapping); + CopyOptions copyOptions = CopyOptions.create().ignoreNullValue().setFieldMapping(fieldPropMapping); return BeanUtil.toBean(entity, pojoClass, copyOptions); } diff --git a/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/repository/MybatisPlusRepository.java b/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/repository/MybatisPlusRepository.java index 1d90048f..5b36fec3 100644 --- a/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/repository/MybatisPlusRepository.java +++ b/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/repository/MybatisPlusRepository.java @@ -17,6 +17,7 @@ package com.gitee.dorive.spring.boot.starter.repository; +import cn.hutool.core.lang.Assert; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.metadata.TableFieldInfo; import com.baomidou.mybatisplus.core.metadata.TableInfo; @@ -67,6 +68,8 @@ public class MybatisPlusRepository extends AbstractRefRepository { } } + Assert.notNull(pojoClass, "The class of pojo cannot be null! source: {}", mapperClass); + Class factoryClass = entityDef.getFactory(); EntityFactory entityFactory; if (factoryClass == Object.class) { @@ -75,35 +78,35 @@ public class MybatisPlusRepository extends AbstractRefRepository { entityFactory = (EntityFactory) getApplicationContext().getBean(factoryClass); } if (entityFactory instanceof DefaultEntityFactory) { + TableInfo tableInfo = TableInfoHelper.getTableInfo(pojoClass); + assert tableInfo != null; + attachments.put(Keys.TABLE_INFO, tableInfo); + + Map aliasFieldMapping = entityEle.newAliasFieldMapping(); + DefaultEntityFactory defaultEntityFactory = (DefaultEntityFactory) entityFactory; defaultEntityFactory.setEntityEle(entityEle); defaultEntityFactory.setPojoClass(pojoClass); - defaultEntityFactory.setAliasPropMapping(entityEle.newAliasPropMap()); - if (pojoClass != null) { - Map aliasPropMapping = entityEle.newAliasPropMap(); - Map propPojoMapping = new LinkedHashMap<>(); - List fieldList = TableInfoHelper.getTableInfo(pojoClass).getFieldList(); - for (TableFieldInfo tableFieldInfo : fieldList) { - String property = tableFieldInfo.getProperty(); - String column = tableFieldInfo.getColumn(); - String prop = aliasPropMapping.get(column); - if (prop != null) { - propPojoMapping.put(prop, property); - } + defaultEntityFactory.setAliasFieldMapping(aliasFieldMapping); + + Map fieldPropMapping = new LinkedHashMap<>(); + + List fieldList = tableInfo.getFieldList(); + for (TableFieldInfo tableFieldInfo : fieldList) { + String property = tableFieldInfo.getProperty(); + String column = tableFieldInfo.getColumn(); + String field = aliasFieldMapping.get(column); + if (field != null) { + fieldPropMapping.put(field, property); } - defaultEntityFactory.setPropPojoMapping(propPojoMapping); } + defaultEntityFactory.setFieldPropMapping(fieldPropMapping); } - TableInfo tableInfo = TableInfoHelper.getTableInfo(pojoClass); - attachments.put(Keys.TABLE_INFO, tableInfo); - Executor executor = new MybatisPlusExecutor(entityDef, entityEle, (BaseMapper) mapper, (Class) pojoClass); executor = new FactoryExecutor(entityEle, entityFactory, executor); - executor = new AliasExecutor(entityEle, executor); attachments.put(Keys.ALIAS_EXECUTOR, executor); - return executor; } -- Gitee From 40171d8bf84bc7fe7ee32a030e6bf710cc602dc7 Mon Sep 17 00:00:00 2001 From: chentaoah <609580885@qq.com> Date: Sat, 15 Apr 2023 16:07:14 +0800 Subject: [PATCH 4/9] =?UTF-8?q?=E5=AE=8C=E5=96=84=E5=AD=97=E6=AE=B5?= =?UTF-8?q?=E6=98=A0=E5=B0=84=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/MybatisPlusRepository.java | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/repository/MybatisPlusRepository.java b/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/repository/MybatisPlusRepository.java index 5b36fec3..8e46d729 100644 --- a/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/repository/MybatisPlusRepository.java +++ b/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/repository/MybatisPlusRepository.java @@ -32,6 +32,7 @@ import com.gitee.dorive.spring.boot.starter.api.Keys; import com.gitee.dorive.spring.boot.starter.impl.SQLExampleBuilder; import com.gitee.dorive.spring.boot.starter.impl.executor.AliasExecutor; import com.gitee.dorive.spring.boot.starter.impl.executor.FactoryExecutor; +import org.apache.commons.lang3.StringUtils; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; @@ -78,19 +79,27 @@ public class MybatisPlusRepository extends AbstractRefRepository { entityFactory = (EntityFactory) getApplicationContext().getBean(factoryClass); } if (entityFactory instanceof DefaultEntityFactory) { - TableInfo tableInfo = TableInfoHelper.getTableInfo(pojoClass); - assert tableInfo != null; - attachments.put(Keys.TABLE_INFO, tableInfo); - - Map aliasFieldMapping = entityEle.newAliasFieldMapping(); - DefaultEntityFactory defaultEntityFactory = (DefaultEntityFactory) entityFactory; defaultEntityFactory.setEntityEle(entityEle); defaultEntityFactory.setPojoClass(pojoClass); + + Map aliasFieldMapping = entityEle.newAliasFieldMapping(); defaultEntityFactory.setAliasFieldMapping(aliasFieldMapping); + TableInfo tableInfo = TableInfoHelper.getTableInfo(pojoClass); + assert tableInfo != null; + attachments.put(Keys.TABLE_INFO, tableInfo); + Map fieldPropMapping = new LinkedHashMap<>(); + String keyColumn = tableInfo.getKeyColumn(); + String keyProperty = tableInfo.getKeyProperty(); + if (StringUtils.isNotBlank(keyColumn) && StringUtils.isNotBlank(keyProperty)) { + String field = aliasFieldMapping.get(keyColumn); + if (field != null) { + fieldPropMapping.put(field, keyProperty); + } + } List fieldList = tableInfo.getFieldList(); for (TableFieldInfo tableFieldInfo : fieldList) { String property = tableFieldInfo.getProperty(); -- Gitee From 22e5c826aa919c1a749d9649bf2d3930e65929b0 Mon Sep 17 00:00:00 2001 From: chentaoah <609580885@qq.com> Date: Sat, 15 Apr 2023 16:26:24 +0800 Subject: [PATCH 5/9] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=9E=B6=E6=9E=84?= =?UTF-8?q?=E5=9B=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/img/framework.png | Bin 29801 -> 25864 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/doc/img/framework.png b/doc/img/framework.png index cc763a43ae8c9119f74aa3a6713e3bf831d4e93d..b8a0004ef5d4b4f78643cdae3bfecc3a7f8f0de8 100644 GIT binary patch literal 25864 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
    fNWLff#kfC93Yy zJ(`N2wDtVWcz@4$1GYsfmYU5=i$G5vzo#j21suI zGPGo32yYVYj_x)3t|)6v-ws2FV}9&< z$H7?~MkMC|yl?&2Qk_mS z>K%e2=YO99yvy4AG$HyXr^@jF>7paK2k|2yrtAzo&k z?$6GQDw>rU&u-QCV<1(f2is~vh=V8a(=Ng%9=qEj50@+>-Azu&L}_{TSXS&xDQqAS zyZJz5_-#kW6t8FD^fm?bkmo}tx#3jeG;3c(1@sCPr!qgNC>;$Gt%abY60$zPsB0%zwf-_}-S$Nkp8UD!sFDlZ) z_-Exo0Ac|LVtu*shm9EXs|Dv#lo{!tm0x}ULX@n(_W#)MuO^~oh5sRBKT-q&H?z#w zKjdIo&M$A@$1?GkpGo*VW^fY{0sqg;WI_?S`~{I+ zp}KzgE|WB;>&m<7Ro;+3l6LJo8o!9y=`_wqP~%Ro#AQY%O6>Z-26{xMzaz5i7+UOt zfg5o8>8oRFj41^H=k-(IfD`{D^utVSHtqeLzkJQl1hvH%_5A%c!VX=&J1wMKv$u4l z$Ev3_VIDsM0@-fHU+L+IH5dkR{BGa)rCJIVvv~TGpLOgdmr9%vha|+s1j{V@t?TEX zmPBF=3H_V?T37|4h;vE0fc=VI^6aasovNpROF*@Bc6D894u7{J$)*3J;?nmroO0l8 z(B2|@)Ye4R!BIZz+RK#GprXHQRB?Bx1jc{fFcigiwk<}@Sgs0bIfK;FrBUW zUIxaKjxc~q-pMHDY4`VX!7Un4AHTX@D4dBC?k0WhhXQ!c@E zy8}ifAJKome+GxX^J*?NRxh1Nui5E3oNl>ZuTzlke?7|GQt#cuTlk$;>Tf`MKhp76 z)_t8w!u|f*c?^N2&PUIa!ZG`$QVuCtO{Ps!PL~sLsMOy_h5@$v+{3lFTg~s=ibZh2 zU`?S&*&%!!<`0Y@g$NNPY9=&y#3p?+GIMU-N7aL;?lCXK%W|L@YIV;0$b8-0C*G*x ziuC+aU~hJ7zF+Fp+1G5CwOf?o!vA`;&+tTrEBX%7{&lrIqI~01zar4&b{}}53p!OR z0m>U%9SG^Ti$WhqD_yLG)kQcFzXK$L9g_XWB@emro%h=VLLn_Ln@@TN3BIyXg_sge zqpCQCg2NzdHymuCLP`n3oroJsqrP+T6{};Eq4B!D@t_ z5W%U1F>1n%s3BJ@>zjb;t zK3dRwfOD>#W5jnI zMD{Ms9~xmS`eSvHqWWOW(dMH*u@L}G31cR`2;jAFHEA+MX}}|%`}Pt5x0-7Nr*Dn) zb$58#{2tF69kZSxN1Rlyn**&G_mY5%Ue{cU5P=Lc6=GTK#XJ=(S54wK*4P-EAy4^v_PAV#f)J= ztt!mb=8l!LPB0>D>Y|bq<_f4Qwzq3F!m7^`~z%c*M?YM5gMEr_MUV-J5uT zO4x&Kpc2-`wQH));fJrx(6Hoz^3*e#Ee;NMls08XEk-u69oOuC2^W%z1}ZcH54K;v zXnS;v5Js+L5+T*}`62tQxQ*}}q5|5T>3b0Uk7Ic@{8QDvW!=Z_kE&hb3N$)vfjX*2 zThv0I(;A*a32$%QVvPsue#+teH=rCNuj=B4c>gP7mt3TVB_4hzE^};Sp(*lZF4(cJ z`=Y-tWfh`GIj1+6BXC_PdA_ud&8TKIy%2n%Q~jg*Wu_obFw+ma#SO0riTbPZy8y@A zez(u|>PgZ#A|Dw{7%o!(St*~|a#5s@8Z>ZsZ`Fr^J0)eTgT1ayf4RCm&z)h}?x)w= zYOj<>%tBJ>L*;vGaq|gyr2N7Adps|H&Q}hEb)VzXaAW**+oiz8BV<><(f1r-KXQOD zztMjb2}UDRtDCzc+9?usAgezTR|U^&57lW3ue@|Qp^D?hn~2h!h0hjYVvAZ{Nmc5$ zO}}eB6wS5=Wd=enr|bu|bh@?@1QJ9ucKjZ^Z%CYMUf#pmKzF1 zg;>m9i$R5E=iPE!&L27Z@Ms;0=E{zj?q;1K`l!bXdngc^?Cf+7=upq`={Nmf1eH81 zi{;tS;$F~#Me~fQVMbzgk3*&>IykbDBy1mtK;<$l;D(gA?}&*JxO=_bk$HER5oP^# zTxBwE{sz3 z-GnzG+a{`mT)b}QkW<1o!$?@?lyU45aNa#L{k8pBSpeUZA)GDC=$W{y0Pm&EiHzDKpBB-3Ce` zAZedx3u$J&@XQZACT(*UuKb2>lS=3H9i1I7m|&N5SIRG1weSeUiL9S_V>3B-dK4Um zu;(Mo`r33@oGQd+>COD0N$HixAbQxS+4kfn>}-6SGGp~x(y~a{uuui%%r-&I5r0PT zo7D=g=&~_r1ki2p?4d&5gdfmwvDwmIvwYa$vQGr>;b~BzHgSzUKRe z<{vH&a1H6u8+CVs-Y+5CV+qtFTGOXm>P5S$M@@fPsk)u;t$cMvWR+6X$<$@Fcc?c> zKzX)5L)ui&)Yol{?R1OhH(9>8{*@rEBYa;z4WQ-wOpd*496Owh;g5WD(BN)^>YWm= zz>6x7B%JU|UrON>_x`c<&Cy4`6wgx9XNU?7dlD*INl0q&nC;nTKM)NAP2~+gqTP zmRH<(Z0P3Z)-`dkSx}NN_4CA}hxQxojJTNw&Yb_dWK9GUHd|AM@A0JMLo+cHuNJDa z=6%>nGmuDZZ_iZBjm{_7q}m=Fj;Qlqm0(z{X6xPRH@_Afu4hMeGo9pJ!tfdOLzSR3 z(5q5?$Lry2LIDW-yS;eH*XOVUAKrqm1-B>Yb<9XJy+O$)iJX)S9e27>?52?{OljSM z>50n${OI18`>0;h8HvI0+5?{Em)9vh%}EJzhA7C%f1ijpsdj zLm6U^EFL@D7&);lP%XT;IOczcma?0@9K}knFSv`^lt;#eqI=V%!LORH-22kR^%9Mp zyQES!F3SvdbH8Dn$=&S&nj`KDO$p+v-HHHO2>ox~4*=Np20)=}B5GO!tC3FexkHhD z*^4Ou>vZ*AnNk3MmtPo{rTT$Y@7G(NXsN)YNHgnirsGh72f|~<|D$1?{FjXz+FFx7 zir!9M9W*xEUBhoxXOqRyP|{FQ$7ez!xjJ9K&yDdCX|x5uQ{8+FG!32a@^H3Sa%l4K z^v$>KR;=)Mw`|NVyn}pylz2b^DmezC(-@+V0T-N0_ZVm}KgBap^1q9+Bj|q+I#nJf zRC{9tTB$Ay)7zOE;fsFB?}LU4V;GKKQ1&|eY(0l`g#zDq8vRr|M^gnK7mP}$OOQM+ zX*tM<2t|Z_hp9Rwm{h6;P4?yuv!S{rKR#$wJ@*=CL498k6u4_|-{TIWrb-0=syf;0 z;tffP$ zGpd(o%6V(DH)ZiZ4zbV9U9K9u0gSci^J?zG0oeEg$*46+vHdd*;D0v+I3eUOoye=r zzdu@Nm#_PBVK}~k%hZ(TTk%A~VRJ0Z!V&v9r|=aq0snKLKa{gA$yV{Jv*mA=byKB$BDD$4)=d| zrsD<3GdMQ4^Ovn$r$5cRJv(pcB=Zni;}^V^RSsiD8HPej zBEOE3Kc&mngM`M>aOUiJwziYV71~>$6K<)b&qsb{Jb^9zA=QQlaO8 z&7I(w3&B2uG%eXSt=Vo>{ll(U)3T~QFVSdd0J<}QW-U5M-pbLW<&ZOV5MAj%p|esM zXbT9e&R;WPpa?upoI6)-XqHQvXOr9q?1H6Cd)G5mek#1+)j%C?5?6W=5=chV&j5^7 z7b9qQ@`;J_4mdlSOyf%Dpu+nI=J2#gxMtEUdH(qDjmyU9+!O$+i=Epw z2zXkLM)|_E+Ji`0-qXMzU8di-@C4(hzI4RP`6tZ(G<|N@-0(b`7NlU3j{Kgz6Jd%2 z76iXCPdXyCIqGhnW=D~EMBw**Op;TryFc&wg!|QxI$rme7s>j%)}xZcIYbghQ1#!* z;;UIdrN`~RGZLjz9J)m|zN-RXS_z(AaLPOr4SZDq@+=Iv3~`_HYvHH@t#B-}YgCU~ z7B{#_PllmAwrwo#+ybRs+7$M?;o=v|%M|utonY=J!F=I#R=$0 z?WFdNaKCEbqWLdfi_rSMz$)@6aVC1Cqth!;r8F%0mEoGAUgvCTWJ*sll0nkkO_xCZw z`H?@4km{PM{GLib<==7t?q95Hxi_P#D&RO3aYgHFCdL?v*WJPXf3x?v9wkG>-EFmLXV;{?Npy<9o z*YoaqKF{;we$O#;9_Mi$=l}mZzQ5m`=POI(Rc$BX7@^+j*J|ahx5?RP2)m_r2{U}~ zG|Rc$uPt9)7g9-09p5SZqbwrI4RXH3_>qha-TKNlnKn5w>iOdt+}X=TNS(TkwMOTh z8t@K?D%a}w2#>dUJcYa{rFq6;qA#0|u@gAS|a&Tv+_=6TV+PT<9axTy|maulb; zj|%G=8%=TD>l%z-a<{H1u8fXYbL9Z%WaoXf6lmqckzh+UI9ad;RT1#v%b3X%*0+69 zffwFuhZ?s6#G0u6_Bx{X$a4Q${~NzLA`vkrrRrr%#@vll>{$PsIZdDc=!hU!Kbti8 zNKKBzl)quL<p^osDHA2O@6qq&QRWUcZhhju%rH=9ImXU5NFmD0Y8z zUAkKh7)=`;<6inkHu;v`@NeOXoeFn0)~SC838*W@CvZH{FJxA%Nf<#Uo3-Q zw&f&{g;Yy0)45AsS%j}ECfpDOCIgBnIXyNQ!0DoZ+ zY&lTuTLm5OXoHm9h`JpW`Xx2<@bapn#Wu>9V_!C$?UW~L(=zr|>v|5@b{_xop& zYhqsiKO)!vuE@34)|Vk_0#rDgCG8+w;aU$bd_9Qlh>}?e13q|tZT{>bH4n_K_LovW+oya~&n?=*Vp|(o$4}3aHD|}6Uo(Q* z;;QdLFgja;{eDi#x8n2dABBE8C_^j`&+jpYX2HArQz$1FwNiM({h>YlW~#h~K~P{Ix*Z;@ zD+lY2ru=}4Fsts#LngWM8JV~mYgO?CnGg{!!>2U1ZBXQ4>e?IZ^W@8(>gqD?niLi0 zckxd=q?6suP{5-B^r^i!@DJn4TOH*?ZN*8}oBlb_GI$zUZg8fDH;eZTg%^IjvI4!7 zl^$am=|jzu?&{Tw%SbM(SbDknLVvF>npo-ykeX4rwqi&1QHIx67`9s%*hxWkn%hXe zSmiWqcG1ginXGpR4Xm3+lYf>69atQYn|3o!HW&>hXyfoyz`uDD6|c z7}ckoT9N4mJCxU6iDFy9YFh;RsdD_>wia;=h=|#fX8hZ$X^B4X*exd1zR!NoCISk7 z+45S~rZ~dfrQsSkTl#3BDXP|pc~g>Tq6784fY2ud;jWr-AN38D>gtS$>)k1JIFxi5 znVL(?>3!o%>Pagu3AdMH`K&%!FQXI^S`;jzPJ*n2*G`tn=bJ!E%Pv?wS~8d-A))8h zUqaLovP-w3#n;2g1ODJ;8!0VcBA^$OJh&Uc|1rV=yl5I39d zx~C*{IjTp&%}FK?3oZ=4b53O#<6pL{b-M+N@1y{{V^jg^d3=&sdttH3PR*-Kd|_I_ zWO#qulocB%hj*CP-{q~_Zxiw>6hOJ_P+edLbd_3_VKD~ETlywm5G|&&!m=mna2zGl zRu+ty1>^CmdsSlX~KD|)U zSi{a$po2?&=k;a{-;3WMg_f-@jP`6)p-?97gOB1I%En`FKfBvboY}ewr5yqm&9fi! zdF$dgr;}Jp6q{^?c!SJaGMt*ZolDPM93Bjuz$WKq=T(>I*NtY)sEVL$-N~^zRU)?Y zeM<>KX3rhUr_$TzH~*U5BF=S3U)I%GySYg0TPB>x`Si9PH*v(R<}Ow&1y>XvlOZ_Y zhw9j&K$+YTAmAgLAz^ZTSZtJKJM`}>Pq?io27x(oNdMJY-}kbt;Yp=T5)K1$@#Ss} z!_2Em{$5*sLloa)F|VMN?`6l_-+CigBHQ}=vw^m!wKCv>y`~SOh`sC-@3HP9uh8mN z-`VERxl@tkIXz!0evGbAGX+lmq~cD+;ogaS{LB(5G$D==wC7EMH^@8phr;MR+{EuRTRRy%I)M7c1XYyDqp? z`C^1K&PZpS&!d-yFlTY4J5Zs$TflE2SQdr&P^78A)Z%E?{8}gtcP)~ol(Obu9L{>6C>rU}#ODh@It|H@~^8U(rW~=#GL*?4ENBq^f=ig+n zXq2RDV(C@Pps4TNq)$jddOXqdz`fYvv+BGc1|30oPxci(38 zb5NRHLD`1A_kxKvHFQ3$F1hA-lNVgB(ydn9Dw^qT)S!V22t`YX!06P#w5cq7vdgv; za#(c>^GmZXCw?H$yUYN`1p@!L&P46a1qXJ^H%`~pUOzKmYCiH~p`KNMxNOz8fDdJs zcFS|C%w02;U?znU#y<9)jpCSZOomQ&2oZY_FVp zBd#@i1niVE0-Qt6WP$B>ceYsk_=3dt7zq6&TlUm1QA9#7w4DB zpZ%6Tz$(^v=}ChfL%$U~UR#@P5I`d+U+gS#Nf^j15GrK=1~+1?iWp@?WS1hsd{PT% zMeL-+`Jbqe3#=c~nijg;33SXATx#`AQE7H?2WfZoFK`DT4x4aB{7eZBi3z5klN=d9 zC4J%Ll8DQGWg0A5;`gm`E z?4Q`AsdKh`)+w#*jq_ar;w7FwE2c|NEbQJ4AFwVb8k`r)YPd~d@^oVbhzIAPHc-}_ z8e5j8^x_A>XpsQ^5=9{o1f|vy(r#}3KF;qZ-)2pkAZo+UG^HPE+|aEpv@=s{1kC;o zg@D?ph95%cGfdkHxaz6~2TY|uR~2XNd^hT(wPWf<)5cLB;HRF@W9M?ZpdcgFW){4P z41-FFWk~XhHky_l`ZF3ovB(`sWIHQPcap2|)2sKCFYBGB!~NY1*ye$3#DQvjBA0(= z`SJ0(OcXV3fIN`DT>GpuV!q@P;;56jyQrR6zI}=zfP|Gu_Y*@qXHm9uafjO0-+u&V zkbT_LmJ^k1ggOZ}0^*a2Rb(~oIqS{|Pvrq=V1kfo&`(!4c-;K$m2YhA7rAQ2d;Dcu^$fv&le zLO%_j3G&=Mo=WlIu&?j^?qc%e>#|sWPII8k9lmKEyU=@L^|VEwhIcD1mJ&K+iCpZS zLZoT?>Nzj_oDf z`mrole%#*uuj4;(bAk{R*q5!cH3;k9R-HbhC1h+JZTu?C)A+xeeuSAEiJ*e2E53K0 zRGk?pt?!bFL_(bmd1odZ;{1N+1Q1Swt`=TG5iLJq5W)(K2TR;Dx|4#0s2lH8+ohi=01)@Sq z*pET2ihL8r6B_lkt?2&MrwGoHD6$~gaKny~9oynY)UxBrpYwoF?&NVV=*?9gIpbY2 zVRgnu>4qUcxRJ8fXWzpyc%vz9!C7W9W@o6E1AkKe-l1?o$A!&PylJK@c3-uFkxlQx zIe-6&1?kP~O(5>c3iN3q#IPw&gpo^#I9BB}*`0#<+R# zONSLoE?f4lxCrC2#y=*bSKaAF*Bsl#a`hW{rs*FPZV(OVh_5yC<-PP1BE@tItgC>7 z+pEj2@(%G@>|oK^^)IjOx_UJ|OcbKNsLq9^McS^H+_0T(z!#ZBQ0I$272BYM&}vKI zrZuqsi#ERbwoyCc5is)qj5aU2#>*=)`aOj!5qb&ZlpsKwgc%Z>{ATaN4w4crS4W?b z`JET)jEO(N;G(0zSZ#)^)@*zJ%)s7@tJc8m>}SWxOAy2>r$^|Jl;^Ciat4#m$lg60 zZrbXMvD$TkDKlZ0Ll2{I{B%T)IO4+? zQaFUSoo&24_0B9B zv~y2o`**Ohl+4#-s2{Q+c%lLX`WDbHRu13L{a3y__0+@Eco&OY57FJfp_duhG?V-y z`R^my;UXB<##VTP%^M5>YUwTuY3S^ZB4_#oDPANUz+n@MeqvMRCbeZh16q80HoTgtvIU2{b)Ci{&k<|xFZJM$aCgI-II9JyT z%K;zv!ymWgV~BJJatZ%4Bw1-#!o@PzLuJ6Xo`3!ZyJO9_wMZhwi6-`s&m;Fv=phxf|=f1M5GzN_kZ|QEakgxja4L6 z8&6pAksVx87*5u+tXHq^V>Up~LpC;4xHR>IyyFqg^&BgYV_V;v?N8@T zio+`9^^e~4Pb5`t&_B|1^omiUl-bVY_sAr=a>G3{rtwPkPGN4wp;qge)+hHL!VYb8 z3<48Lj7BsoDramz@#N0+EZUk#FcEPg5xDvpBy~STBNNMDXomVRxNem6Nn7u z-ydwpcJn6J+=Js)4r~<*U$+g4C)7=Jgc^#up~IYvEX4=2#R1a8Ia_&pNcTbVb0F5% z_7IEy0S|l{h{KWJ>Fj`W<=0$L0}qVYp|Grj#T5iL7PZA=;s+y>1MmB}$13{2ztV+p zC7?`mc#**mCiKV-4Ua|uEcBOYLzNwDN2ja&HTOq;dw7S2AHD^mq<=k#91%dz4uaNj z?T`HR5csbn^O?u?FCr3f?Qu$Z_h|P=wt5U`_`@E0&-O1uZ3iz+fqXc+KeFgGK*JxB i$vRjb|JT#A1^ZqZczaz2yYmYtht!m{l#qYj^Zzd&r#dMB literal 29801 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

    F4ibJi&PTbYfV1J$!55z< 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 -- Gitee From 6cee8043a921a7e52e8e5231c1fd2b08f0a275d5 Mon Sep 17 00:00:00 2001 From: chentaoah <609580885@qq.com> Date: Sat, 15 Apr 2023 17:15:27 +0800 Subject: [PATCH 6/9] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=B8=80=E4=B8=AA?= =?UTF-8?q?=E5=88=A4=E6=96=AD=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../boot/starter/repository/MybatisPlusRepository.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/repository/MybatisPlusRepository.java b/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/repository/MybatisPlusRepository.java index 8e46d729..068ecf6e 100644 --- a/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/repository/MybatisPlusRepository.java +++ b/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/repository/MybatisPlusRepository.java @@ -71,6 +71,10 @@ public class MybatisPlusRepository extends AbstractRefRepository { Assert.notNull(pojoClass, "The class of pojo cannot be null! source: {}", mapperClass); + TableInfo tableInfo = TableInfoHelper.getTableInfo(pojoClass); + assert tableInfo != null; + attachments.put(Keys.TABLE_INFO, tableInfo); + Class factoryClass = entityDef.getFactory(); EntityFactory entityFactory; if (factoryClass == Object.class) { @@ -86,12 +90,7 @@ public class MybatisPlusRepository extends AbstractRefRepository { Map aliasFieldMapping = entityEle.newAliasFieldMapping(); defaultEntityFactory.setAliasFieldMapping(aliasFieldMapping); - TableInfo tableInfo = TableInfoHelper.getTableInfo(pojoClass); - assert tableInfo != null; - attachments.put(Keys.TABLE_INFO, tableInfo); - Map fieldPropMapping = new LinkedHashMap<>(); - String keyColumn = tableInfo.getKeyColumn(); String keyProperty = tableInfo.getKeyProperty(); if (StringUtils.isNotBlank(keyColumn) && StringUtils.isNotBlank(keyProperty)) { -- Gitee From 549ac33114f809be147249c1f9a90bcd3dd67897 Mon Sep 17 00:00:00 2001 From: chentaoah <609580885@qq.com> Date: Sat, 15 Apr 2023 17:21:04 +0800 Subject: [PATCH 7/9] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=B8=80=E4=B8=AA?= =?UTF-8?q?=E5=88=A4=E6=96=AD=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../boot/starter/repository/MybatisPlusRepository.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/repository/MybatisPlusRepository.java b/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/repository/MybatisPlusRepository.java index 068ecf6e..ad843fb4 100644 --- a/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/repository/MybatisPlusRepository.java +++ b/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/repository/MybatisPlusRepository.java @@ -90,16 +90,17 @@ public class MybatisPlusRepository extends AbstractRefRepository { Map aliasFieldMapping = entityEle.newAliasFieldMapping(); defaultEntityFactory.setAliasFieldMapping(aliasFieldMapping); - Map fieldPropMapping = new LinkedHashMap<>(); String keyColumn = tableInfo.getKeyColumn(); String keyProperty = tableInfo.getKeyProperty(); + List fieldList = tableInfo.getFieldList(); + + Map fieldPropMapping = new LinkedHashMap<>(); if (StringUtils.isNotBlank(keyColumn) && StringUtils.isNotBlank(keyProperty)) { String field = aliasFieldMapping.get(keyColumn); if (field != null) { fieldPropMapping.put(field, keyProperty); } } - List fieldList = tableInfo.getFieldList(); for (TableFieldInfo tableFieldInfo : fieldList) { String property = tableFieldInfo.getProperty(); String column = tableFieldInfo.getColumn(); -- Gitee From a4f562cf8e1d78c1b24d8fb8bc40853205a9b29b Mon Sep 17 00:00:00 2001 From: chentaoah <609580885@qq.com> Date: Sat, 15 Apr 2023 20:56:17 +0800 Subject: [PATCH 8/9] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E7=B1=BB=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gitee/dorive/api/constant/Operator.java | 1 + ...atingObj.java => CoatingRepositories.java} | 6 +-- ...sitoryObj.java => PropertyRepository.java} | 9 ++--- .../coating/impl/DefaultExampleBuilder.java | 28 ++++++------- ....java => CoatingRepositoriesResolver.java} | 38 +++++++++--------- .../repository/AbstractCoatingRepository.java | 6 +-- .../dorive/core/entity/executor/Example.java | 40 +++++++++---------- .../boot/starter/impl/AppenderContext.java | 22 +++++++--- .../boot/starter/impl/SQLExampleBuilder.java | 28 ++++++------- 9 files changed, 94 insertions(+), 84 deletions(-) rename dorive-coating/src/main/java/com/gitee/dorive/coating/entity/{CoatingObj.java => CoatingRepositories.java} (87%) rename dorive-coating/src/main/java/com/gitee/dorive/coating/entity/{RepositoryObj.java => PropertyRepository.java} (84%) rename dorive-coating/src/main/java/com/gitee/dorive/coating/impl/resolver/{CoatingObjResolver.java => CoatingRepositoriesResolver.java} (77%) diff --git a/dorive-api/src/main/java/com/gitee/dorive/api/constant/Operator.java b/dorive-api/src/main/java/com/gitee/dorive/api/constant/Operator.java index 47c5b17e..deb505aa 100644 --- a/dorive-api/src/main/java/com/gitee/dorive/api/constant/Operator.java +++ b/dorive-api/src/main/java/com/gitee/dorive/api/constant/Operator.java @@ -30,4 +30,5 @@ public interface Operator { String NOT_LIKE = "NOT LIKE"; String IS_NULL = "IS NULL"; String IS_NOT_NULL = "IS NOT NULL"; + String NULLABLE = "NULLABLE"; } diff --git a/dorive-coating/src/main/java/com/gitee/dorive/coating/entity/CoatingObj.java b/dorive-coating/src/main/java/com/gitee/dorive/coating/entity/CoatingRepositories.java similarity index 87% rename from dorive-coating/src/main/java/com/gitee/dorive/coating/entity/CoatingObj.java rename to dorive-coating/src/main/java/com/gitee/dorive/coating/entity/CoatingRepositories.java index 00fbe40e..cedfb04f 100644 --- a/dorive-coating/src/main/java/com/gitee/dorive/coating/entity/CoatingObj.java +++ b/dorive-coating/src/main/java/com/gitee/dorive/coating/entity/CoatingRepositories.java @@ -25,9 +25,9 @@ import java.util.List; @Data @AllArgsConstructor -public class CoatingObj { +public class CoatingRepositories { private CoatingDef coatingDef; - private List repositoryObjs; - private List reversedRepositoryObjs; + private List propertyRepositories; + private List reversedPropertyRepositories; private SpecificProperties specificProperties; } diff --git a/dorive-coating/src/main/java/com/gitee/dorive/coating/entity/RepositoryObj.java b/dorive-coating/src/main/java/com/gitee/dorive/coating/entity/PropertyRepository.java similarity index 84% rename from dorive-coating/src/main/java/com/gitee/dorive/coating/entity/RepositoryObj.java rename to dorive-coating/src/main/java/com/gitee/dorive/coating/entity/PropertyRepository.java index 46a7f79f..d6c8299f 100644 --- a/dorive-coating/src/main/java/com/gitee/dorive/coating/entity/RepositoryObj.java +++ b/dorive-coating/src/main/java/com/gitee/dorive/coating/entity/PropertyRepository.java @@ -18,7 +18,6 @@ package com.gitee.dorive.coating.entity; import com.gitee.dorive.coating.entity.def.PropertyDef; -import com.gitee.dorive.core.api.context.Context; import com.gitee.dorive.core.entity.executor.Criterion; import com.gitee.dorive.core.entity.executor.Example; import lombok.AllArgsConstructor; @@ -28,20 +27,20 @@ import java.util.List; @Data @AllArgsConstructor -public class RepositoryObj { +public class PropertyRepository { private MergedRepository mergedRepository; private List collectedProperties; - public Example newExampleByCoating(Context context, Object coating) { + public Example newExampleByCoating(Object coating) { Example example = new Example(); for (Property property : collectedProperties) { Object fieldValue = property.getFieldValue(coating); if (fieldValue != null) { PropertyDef propertyDef = property.getPropertyDef(); - String field = propertyDef.getField(); + String fieldName = propertyDef.getField(); String operator = propertyDef.getOperator(); - example.addCriterion(new Criterion(field, operator, fieldValue)); + example.addCriterion(new Criterion(fieldName, operator, fieldValue)); } } return example; diff --git a/dorive-coating/src/main/java/com/gitee/dorive/coating/impl/DefaultExampleBuilder.java b/dorive-coating/src/main/java/com/gitee/dorive/coating/impl/DefaultExampleBuilder.java index 819aef52..486b8aa6 100644 --- a/dorive-coating/src/main/java/com/gitee/dorive/coating/impl/DefaultExampleBuilder.java +++ b/dorive-coating/src/main/java/com/gitee/dorive/coating/impl/DefaultExampleBuilder.java @@ -20,10 +20,10 @@ package com.gitee.dorive.coating.impl; import cn.hutool.core.lang.Assert; import com.gitee.dorive.api.entity.element.PropChain; import com.gitee.dorive.coating.api.ExampleBuilder; -import com.gitee.dorive.coating.entity.CoatingObj; +import com.gitee.dorive.coating.entity.CoatingRepositories; import com.gitee.dorive.coating.entity.MergedRepository; -import com.gitee.dorive.coating.entity.RepositoryObj; -import com.gitee.dorive.coating.impl.resolver.CoatingObjResolver; +import com.gitee.dorive.coating.entity.PropertyRepository; +import com.gitee.dorive.coating.impl.resolver.CoatingRepositoriesResolver; import com.gitee.dorive.coating.repository.AbstractCoatingRepository; import com.gitee.dorive.core.api.context.Context; import com.gitee.dorive.core.entity.executor.Example; @@ -49,18 +49,18 @@ public class DefaultExampleBuilder implements ExampleBuilder { @Override public Example buildExample(Context context, Object coating) { - CoatingObjResolver coatingObjResolver = repository.getCoatingObjResolver(); - Map, CoatingObj> coatingObjMap = coatingObjResolver.getCoatingObjMap(); + CoatingRepositoriesResolver coatingRepositoriesResolver = repository.getCoatingRepositoriesResolver(); + Map nameCoatingRepositoriesMap = coatingRepositoriesResolver.getNameCoatingRepositoriesMap(); - CoatingObj coatingObj = coatingObjMap.get(coating.getClass()); - Assert.notNull(coatingObj, "No coating object exists!"); + CoatingRepositories coatingRepositories = nameCoatingRepositoriesMap.get(coating.getClass().getName()); + Assert.notNull(coatingRepositories, "No coating object exists!"); Map repoCriterionMap = new LinkedHashMap<>(); - for (RepositoryObj repositoryObj : coatingObj.getReversedRepositoryObjs()) { - Example example = repositoryObj.newExampleByCoating(context, coating); - RepoCriterion repoCriterion = new RepoCriterion(repositoryObj, example); + for (PropertyRepository propertyRepository : coatingRepositories.getReversedPropertyRepositories()) { + Example example = propertyRepository.newExampleByCoating(coating); + RepoCriterion repoCriterion = new RepoCriterion(propertyRepository, example); - MergedRepository mergedRepository = repositoryObj.getMergedRepository(); + MergedRepository mergedRepository = propertyRepository.getMergedRepository(); String absoluteAccessPath = mergedRepository.getAbsoluteAccessPath(); String relativeAccessPath = mergedRepository.isMerged() ? absoluteAccessPath + "/" : absoluteAccessPath; repoCriterionMap.put(relativeAccessPath, repoCriterion); @@ -77,10 +77,10 @@ public class DefaultExampleBuilder implements ExampleBuilder { repoCriterionMap.forEach((accessPath, repoCriterion) -> { if ("/".equals(accessPath)) return; - RepositoryObj repositoryObj = repoCriterion.getRepositoryObj(); + PropertyRepository propertyRepository = repoCriterion.getPropertyRepository(); Example example = repoCriterion.getExample(); - MergedRepository mergedRepository = repositoryObj.getMergedRepository(); + MergedRepository mergedRepository = propertyRepository.getMergedRepository(); String lastAccessPath = mergedRepository.getLastAccessPath(); CommonRepository definedRepository = mergedRepository.getDefinedRepository(); CommonRepository executedRepository = mergedRepository.getExecutedRepository(); @@ -149,7 +149,7 @@ public class DefaultExampleBuilder implements ExampleBuilder { @Data @AllArgsConstructor public static class RepoCriterion { - private RepositoryObj repositoryObj; + private PropertyRepository propertyRepository; private Example example; } diff --git a/dorive-coating/src/main/java/com/gitee/dorive/coating/impl/resolver/CoatingObjResolver.java b/dorive-coating/src/main/java/com/gitee/dorive/coating/impl/resolver/CoatingRepositoriesResolver.java similarity index 77% rename from dorive-coating/src/main/java/com/gitee/dorive/coating/impl/resolver/CoatingObjResolver.java rename to dorive-coating/src/main/java/com/gitee/dorive/coating/impl/resolver/CoatingRepositoriesResolver.java index f429b30d..a26b9def 100644 --- a/dorive-coating/src/main/java/com/gitee/dorive/coating/impl/resolver/CoatingObjResolver.java +++ b/dorive-coating/src/main/java/com/gitee/dorive/coating/impl/resolver/CoatingRepositoriesResolver.java @@ -35,15 +35,15 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.regex.Pattern; @Data -public class CoatingObjResolver { +public class CoatingRepositoriesResolver { private static Map>> scannedClasses = new ConcurrentHashMap<>(); private AbstractCoatingRepository repository; - private Map, CoatingObj> coatingObjMap = new ConcurrentHashMap<>(); - private Map nameCoatingObjMap = new ConcurrentHashMap<>(); + private Map, CoatingRepositories> classCoatingRepositoriesMap = new ConcurrentHashMap<>(); + private Map nameCoatingRepositoriesMap = new ConcurrentHashMap<>(); - public CoatingObjResolver(AbstractCoatingRepository repository) throws Exception { + public CoatingRepositoriesResolver(AbstractCoatingRepository repository) throws Exception { this.repository = repository; resolve(); } @@ -99,25 +99,25 @@ public class CoatingObjResolver { } }); - List repositoryObjs = collectRepositoryObjs(belongToPropertyMap, fieldPropertyMap); - checkFieldNames(coatingClass, fieldNames, repositoryObjs); + List propertyRepositories = collectRepositories(belongToPropertyMap, fieldPropertyMap); + checkFieldNames(coatingClass, fieldNames, propertyRepositories); - List reversedRepositoryObjs = new ArrayList<>(repositoryObjs); - Collections.reverse(reversedRepositoryObjs); + List reversedPropertyRepositories = new ArrayList<>(propertyRepositories); + Collections.reverse(reversedPropertyRepositories); CoatingDef coatingDef = CoatingDef.fromElement(coatingClass); - CoatingObj coatingObj = new CoatingObj(coatingDef, repositoryObjs, reversedRepositoryObjs, specificProperties); - coatingObjMap.put(coatingClass, coatingObj); - nameCoatingObjMap.put(coatingClass.getName(), coatingObj); + CoatingRepositories coatingRepositories = new CoatingRepositories(coatingDef, propertyRepositories, reversedPropertyRepositories, specificProperties); + classCoatingRepositoriesMap.put(coatingClass, coatingRepositories); + nameCoatingRepositoriesMap.put(coatingClass.getName(), coatingRepositories); } } } - private List collectRepositoryObjs(Map> belongToPropertyMap, Map fieldPropertyMap) { + private List collectRepositories(Map> belongToPropertyMap, Map fieldPropertyMap) { MergedRepositoryResolver mergedRepositoryResolver = repository.getMergedRepositoryResolver(); Map mergedRepositoryMap = mergedRepositoryResolver.getMergedRepositoryMap(); - List repositoryObjs = new ArrayList<>(); + List propertyRepositories = new ArrayList<>(); for (MergedRepository mergedRepository : mergedRepositoryMap.values()) { String absoluteAccessPath = mergedRepository.getAbsoluteAccessPath(); @@ -140,18 +140,18 @@ public class CoatingObjResolver { } if (!properties.isEmpty() || repository.isBoundEntity()) { - RepositoryObj repositoryObj = new RepositoryObj(mergedRepository, properties); - repositoryObjs.add(repositoryObj); + PropertyRepository propertyRepository = new PropertyRepository(mergedRepository, properties); + propertyRepositories.add(propertyRepository); } } - return repositoryObjs; + return propertyRepositories; } - private void checkFieldNames(Class coatingClass, Set fieldNames, List repositoryObjs) { + private void checkFieldNames(Class coatingClass, Set fieldNames, List propertyRepositories) { Set remainFieldNames = new LinkedHashSet<>(fieldNames); - for (RepositoryObj repositoryObj : repositoryObjs) { - for (Property property : repositoryObj.getCollectedProperties()) { + for (PropertyRepository propertyRepository : propertyRepositories) { + for (Property property : propertyRepository.getCollectedProperties()) { remainFieldNames.remove(property.getName()); } } diff --git a/dorive-coating/src/main/java/com/gitee/dorive/coating/repository/AbstractCoatingRepository.java b/dorive-coating/src/main/java/com/gitee/dorive/coating/repository/AbstractCoatingRepository.java index 04f43401..afc4e9d9 100644 --- a/dorive-coating/src/main/java/com/gitee/dorive/coating/repository/AbstractCoatingRepository.java +++ b/dorive-coating/src/main/java/com/gitee/dorive/coating/repository/AbstractCoatingRepository.java @@ -21,7 +21,7 @@ import com.gitee.dorive.coating.annotation.CoatingScan; import com.gitee.dorive.coating.api.CoatingRepository; import com.gitee.dorive.coating.api.ExampleBuilder; import com.gitee.dorive.coating.impl.DefaultExampleBuilder; -import com.gitee.dorive.coating.impl.resolver.CoatingObjResolver; +import com.gitee.dorive.coating.impl.resolver.CoatingRepositoriesResolver; import com.gitee.dorive.coating.impl.resolver.MergedRepositoryResolver; import com.gitee.dorive.api.annotation.Repository; import com.gitee.dorive.core.api.context.Context; @@ -45,7 +45,7 @@ public abstract class AbstractCoatingRepository extends AbstractEventRepo private String[] scanPackages; private String regex; private MergedRepositoryResolver mergedRepositoryResolver; - private CoatingObjResolver coatingObjResolver; + private CoatingRepositoriesResolver coatingRepositoriesResolver; private ExampleBuilder exampleBuilder; @Override @@ -59,7 +59,7 @@ public abstract class AbstractCoatingRepository extends AbstractEventRepo this.regex = StringUtils.isBlank(coatingScan.regex()) ? "^" + getEntityClass().getSimpleName() + ".*" : coatingScan.regex(); this.mergedRepositoryResolver = new MergedRepositoryResolver(this); - this.coatingObjResolver = new CoatingObjResolver(this); + this.coatingRepositoriesResolver = new CoatingRepositoriesResolver(this); if ("default".equals(querier)) { this.exampleBuilder = new DefaultExampleBuilder(this); } diff --git a/dorive-core/src/main/java/com/gitee/dorive/core/entity/executor/Example.java b/dorive-core/src/main/java/com/gitee/dorive/core/entity/executor/Example.java index 81ce4394..28b6814b 100644 --- a/dorive-core/src/main/java/com/gitee/dorive/core/entity/executor/Example.java +++ b/dorive-core/src/main/java/com/gitee/dorive/core/entity/executor/Example.java @@ -86,53 +86,53 @@ public class Example { return this; } - public Example in(String property, Object value) { - criteria.add(new Criterion(property, Operator.IN, value)); + public Example gt(String property, Object value) { + criteria.add(new Criterion(property, Operator.GT, value)); return this; } - public Example notIn(String property, Object value) { - criteria.add(new Criterion(property, Operator.NOT_IN, value)); + public Example ge(String property, Object value) { + criteria.add(new Criterion(property, Operator.GE, value)); return this; } - public Example isNull(String property) { - criteria.add(new Criterion(property, Operator.IS_NULL, null)); + public Example lt(String property, Object value) { + criteria.add(new Criterion(property, Operator.LT, value)); return this; } - public Example isNotNull(String property) { - criteria.add(new Criterion(property, Operator.IS_NOT_NULL, null)); + public Example le(String property, Object value) { + criteria.add(new Criterion(property, Operator.LE, value)); return this; } - public Example like(String property, Object value) { - criteria.add(new Criterion(property, Operator.LIKE, value)); + public Example in(String property, Object value) { + criteria.add(new Criterion(property, Operator.IN, value)); return this; } - public Example notLike(String property, Object value) { - criteria.add(new Criterion(property, Operator.NOT_LIKE, value)); + public Example notIn(String property, Object value) { + criteria.add(new Criterion(property, Operator.NOT_IN, value)); return this; } - public Example gt(String property, Object value) { - criteria.add(new Criterion(property, Operator.GT, value)); + public Example like(String property, Object value) { + criteria.add(new Criterion(property, Operator.LIKE, value)); return this; } - public Example ge(String property, Object value) { - criteria.add(new Criterion(property, Operator.GE, value)); + public Example notLike(String property, Object value) { + criteria.add(new Criterion(property, Operator.NOT_LIKE, value)); return this; } - public Example lt(String property, Object value) { - criteria.add(new Criterion(property, Operator.LT, value)); + public Example isNull(String property) { + criteria.add(new Criterion(property, Operator.IS_NULL, null)); return this; } - public Example le(String property, Object value) { - criteria.add(new Criterion(property, Operator.LE, value)); + public Example isNotNull(String property) { + criteria.add(new Criterion(property, Operator.IS_NOT_NULL, null)); return this; } diff --git a/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/impl/AppenderContext.java b/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/impl/AppenderContext.java index 3d0e17e0..0bc916cf 100644 --- a/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/impl/AppenderContext.java +++ b/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/impl/AppenderContext.java @@ -45,16 +45,26 @@ public class AppenderContext { abstractWrapper.ne(property, value); } }); - OPERATOR_CRITERION_APPENDER_MAP.put(Operator.IN, (abstractWrapper, property, value) -> abstractWrapper.in(property, (Collection) value)); - OPERATOR_CRITERION_APPENDER_MAP.put(Operator.NOT_IN, (abstractWrapper, property, value) -> abstractWrapper.notIn(property, (Collection) value)); - OPERATOR_CRITERION_APPENDER_MAP.put(Operator.IS_NULL, (abstractWrapper, property, value) -> abstractWrapper.isNull(property)); - OPERATOR_CRITERION_APPENDER_MAP.put(Operator.IS_NOT_NULL, (abstractWrapper, property, value) -> abstractWrapper.isNotNull(property)); - OPERATOR_CRITERION_APPENDER_MAP.put(Operator.LIKE, (abstractWrapper, property, value) -> abstractWrapper.like(property, SqlUtils.toLike(value))); - OPERATOR_CRITERION_APPENDER_MAP.put(Operator.NOT_LIKE, (abstractWrapper, property, value) -> abstractWrapper.notLike(property, SqlUtils.toLike(value))); OPERATOR_CRITERION_APPENDER_MAP.put(Operator.GT, Compare::gt); OPERATOR_CRITERION_APPENDER_MAP.put(Operator.GE, Compare::ge); OPERATOR_CRITERION_APPENDER_MAP.put(Operator.LT, Compare::lt); OPERATOR_CRITERION_APPENDER_MAP.put(Operator.LE, Compare::le); + OPERATOR_CRITERION_APPENDER_MAP.put(Operator.IN, (abstractWrapper, property, value) -> abstractWrapper.in(property, (Collection) value)); + OPERATOR_CRITERION_APPENDER_MAP.put(Operator.NOT_IN, (abstractWrapper, property, value) -> abstractWrapper.notIn(property, (Collection) value)); + OPERATOR_CRITERION_APPENDER_MAP.put(Operator.LIKE, (abstractWrapper, property, value) -> abstractWrapper.like(property, SqlUtils.toLike(value))); + OPERATOR_CRITERION_APPENDER_MAP.put(Operator.NOT_LIKE, (abstractWrapper, property, value) -> abstractWrapper.notLike(property, SqlUtils.toLike(value))); + OPERATOR_CRITERION_APPENDER_MAP.put(Operator.IS_NULL, (abstractWrapper, property, value) -> abstractWrapper.isNull(property)); + OPERATOR_CRITERION_APPENDER_MAP.put(Operator.IS_NOT_NULL, (abstractWrapper, property, value) -> abstractWrapper.isNotNull(property)); + OPERATOR_CRITERION_APPENDER_MAP.put(Operator.NULLABLE, (abstractWrapper, property, value) -> { + if (value instanceof Boolean) { + Boolean flag = (Boolean) value; + if (flag) { + abstractWrapper.isNull(property); + } else { + abstractWrapper.isNotNull(property); + } + } + }); } } diff --git a/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/impl/SQLExampleBuilder.java b/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/impl/SQLExampleBuilder.java index 2bb466cb..9dd21269 100644 --- a/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/impl/SQLExampleBuilder.java +++ b/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/impl/SQLExampleBuilder.java @@ -24,11 +24,11 @@ import com.baomidou.mybatisplus.core.metadata.TableInfo; import com.baomidou.mybatisplus.extension.toolkit.SqlRunner; import com.gitee.dorive.api.constant.Operator; import com.gitee.dorive.coating.api.ExampleBuilder; -import com.gitee.dorive.coating.entity.CoatingObj; +import com.gitee.dorive.coating.entity.CoatingRepositories; import com.gitee.dorive.coating.entity.MergedRepository; -import com.gitee.dorive.coating.entity.RepositoryObj; +import com.gitee.dorive.coating.entity.PropertyRepository; import com.gitee.dorive.coating.entity.SpecificProperties; -import com.gitee.dorive.coating.impl.resolver.CoatingObjResolver; +import com.gitee.dorive.coating.impl.resolver.CoatingRepositoriesResolver; import com.gitee.dorive.coating.repository.AbstractCoatingRepository; import com.gitee.dorive.core.api.context.Context; import com.gitee.dorive.core.entity.executor.Criterion; @@ -65,20 +65,20 @@ public class SQLExampleBuilder implements ExampleBuilder { @Override public Example buildExample(Context context, Object coating) { - CoatingObjResolver coatingObjResolver = repository.getCoatingObjResolver(); - Map nameCoatingObjMap = coatingObjResolver.getNameCoatingObjMap(); + CoatingRepositoriesResolver coatingRepositoriesResolver = repository.getCoatingRepositoriesResolver(); + Map nameCoatingRepositoriesMap = coatingRepositoriesResolver.getNameCoatingRepositoriesMap(); - CoatingObj coatingObj = nameCoatingObjMap.get(coating.getClass().getName()); - Assert.notNull(coatingObj, "No coating object exists!"); - List repositoryObjs = coatingObj.getRepositoryObjs(); + CoatingRepositories coatingRepositories = nameCoatingRepositoriesMap.get(coating.getClass().getName()); + Assert.notNull(coatingRepositories, "No coating object exists!"); + List propertyRepositories = coatingRepositories.getPropertyRepositories(); - Map sqlSegmentMap = new LinkedHashMap<>(repositoryObjs.size() * 4 / 3 + 1); + Map sqlSegmentMap = new LinkedHashMap<>(propertyRepositories.size() * 4 / 3 + 1); SqlSegment rootSqlSegment = null; char letter = 'a'; boolean anyDirtyQuery = false; - for (RepositoryObj repositoryObj : repositoryObjs) { - MergedRepository mergedRepository = repositoryObj.getMergedRepository(); + for (PropertyRepository propertyRepository : propertyRepositories) { + MergedRepository mergedRepository = propertyRepository.getMergedRepository(); String lastAccessPath = mergedRepository.getLastAccessPath(); String absoluteAccessPath = mergedRepository.getAbsoluteAccessPath(); CommonRepository definedRepository = mergedRepository.getDefinedRepository(); @@ -88,14 +88,14 @@ public class SQLExampleBuilder implements ExampleBuilder { BinderResolver binderResolver = definedRepository.getBinderResolver(); Map attachments = executedRepository.getAttachments(); - AliasExecutor aliasExecutor = (AliasExecutor) attachments.get(Keys.ALIAS_EXECUTOR); TableInfo tableInfo = (TableInfo) attachments.get(Keys.TABLE_INFO); + AliasExecutor aliasExecutor = (AliasExecutor) attachments.get(Keys.ALIAS_EXECUTOR); String tableName = tableInfo.getTableName(); String tableAlias = String.valueOf(letter); letter = (char) (letter + 1); - Example example = repositoryObj.newExampleByCoating(context, coating); + Example example = propertyRepository.newExampleByCoating(coating); aliasExecutor.convert(example); boolean dirtyQuery = example.isDirtyQuery(); @@ -116,7 +116,7 @@ public class SQLExampleBuilder implements ExampleBuilder { } } - SpecificProperties properties = coatingObj.getSpecificProperties(); + SpecificProperties properties = coatingRepositories.getSpecificProperties(); OrderBy orderBy = properties.newOrderBy(coating); Page page = properties.newPage(coating); -- Gitee From e688ea7c9f076a3759c365452ee685dc14f42fc9 Mon Sep 17 00:00:00 2001 From: chentaoah <609580885@qq.com> Date: Sat, 15 Apr 2023 20:58:52 +0800 Subject: [PATCH 9/9] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E7=B1=BB=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../boot/starter/repository/MybatisPlusRepository.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/repository/MybatisPlusRepository.java b/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/repository/MybatisPlusRepository.java index ad843fb4..0f8d0139 100644 --- a/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/repository/MybatisPlusRepository.java +++ b/dorive-spring-boot-starter/src/main/java/com/gitee/dorive/spring/boot/starter/repository/MybatisPlusRepository.java @@ -102,11 +102,9 @@ public class MybatisPlusRepository extends AbstractRefRepository { } } for (TableFieldInfo tableFieldInfo : fieldList) { - String property = tableFieldInfo.getProperty(); - String column = tableFieldInfo.getColumn(); - String field = aliasFieldMapping.get(column); + String field = aliasFieldMapping.get(tableFieldInfo.getColumn()); if (field != null) { - fieldPropMapping.put(field, property); + fieldPropMapping.put(field, tableFieldInfo.getProperty()); } } defaultEntityFactory.setFieldPropMapping(fieldPropMapping); -- Gitee