From e733980e33320502fb574dfae838b6768485f2e6 Mon Sep 17 00:00:00 2001 From: redkale Date: Tue, 4 Jun 2024 19:46:46 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0FilterOrs=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/redkale/source/EntityBuilder.java | 17 ++--- .../java/org/redkale/source/FilterColumn.java | 3 +- .../java/org/redkale/source/FilterGroup.java | 25 ++++---- .../org/redkale/source/FilterNodeBean.java | 64 ++++++++----------- .../java/org/redkale/source/FilterOrs.java | 34 ++++++++++ src/main/java/org/redkale/util/Copier.java | 17 +++-- .../redkale/test/source/FilterNodeTest.java | 12 ++-- 7 files changed, 101 insertions(+), 71 deletions(-) create mode 100644 src/main/java/org/redkale/source/FilterOrs.java diff --git a/src/main/java/org/redkale/source/EntityBuilder.java b/src/main/java/org/redkale/source/EntityBuilder.java index b8ddc0bd6..d8f667ab8 100644 --- a/src/main/java/org/redkale/source/EntityBuilder.java +++ b/src/main/java/org/redkale/source/EntityBuilder.java @@ -46,7 +46,7 @@ public class EntityBuilder { // key:类字段名, value:数据库字段名 // 只有field.name 与 Column.name不同才存放在aliasmap里. @Nullable - private final Map aliasmap; + private final Map aliasMap; // Entity构建器参数Attribute, 数组个数与constructorParameters相同 @Nullable @@ -71,7 +71,7 @@ public class EntityBuilder { EntityBuilder( Class type, Creator creator, - Map aliasmap, + Map aliasMap, String[] constructorParameters, Attribute[] constructorAttributes, Attribute[] unconstructorAttributes, @@ -79,7 +79,7 @@ public class EntityBuilder { Attribute[] queryAttributes) { this.type = type; this.creator = creator; - this.aliasmap = aliasmap; + this.aliasMap = aliasMap; this.constructorParameters = constructorParameters; this.constructorAttributes = constructorAttributes; this.unconstructorAttributes = unconstructorAttributes; @@ -127,7 +127,8 @@ public class EntityBuilder { } } } catch (Exception e) { - throw new SourceException(type + " cannot find ConstructorParameters Creator"); + throw new SourceException(type + " cannot find " + + org.redkale.annotation.ConstructorParameters.class.getSimpleName() + " Creator"); } } Class cltmp = type; @@ -569,11 +570,11 @@ public class EntityBuilder { * @return String */ public String getSQLColumn(String tabalis, String fieldname) { - return this.aliasmap == null + return this.aliasMap == null ? (tabalis == null ? fieldname : (tabalis + '.' + fieldname)) : (tabalis == null - ? aliasmap.getOrDefault(fieldname, fieldname) - : (tabalis + '.' + aliasmap.getOrDefault(fieldname, fieldname))); + ? aliasMap.getOrDefault(fieldname, fieldname) + : (tabalis + '.' + aliasMap.getOrDefault(fieldname, fieldname))); } public boolean hasConstructorAttribute() { @@ -587,7 +588,7 @@ public class EntityBuilder { */ @ConvertDisabled public boolean isNoAlias() { - return this.aliasmap == null; + return this.aliasMap == null; } @ConvertDisabled diff --git a/src/main/java/org/redkale/source/FilterColumn.java b/src/main/java/org/redkale/source/FilterColumn.java index 6a2677e44..ea4ae7b55 100644 --- a/src/main/java/org/redkale/source/FilterColumn.java +++ b/src/main/java/org/redkale/source/FilterColumn.java @@ -5,11 +5,10 @@ */ package org.redkale.source; +import java.lang.annotation.*; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.RetentionPolicy.RUNTIME; -import java.lang.annotation.*; - /** * 过滤字段标记 * diff --git a/src/main/java/org/redkale/source/FilterGroup.java b/src/main/java/org/redkale/source/FilterGroup.java index 1c9e938b3..2a77b5013 100644 --- a/src/main/java/org/redkale/source/FilterGroup.java +++ b/src/main/java/org/redkale/source/FilterGroup.java @@ -5,28 +5,27 @@ */ package org.redkale.source; +import java.lang.annotation.*; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.RetentionPolicy.RUNTIME; -import java.lang.annotation.*; - /** * 默认情况下FilterBean下的过滤字段之间是AND关系。
- * 当需要使用OR或AND OR组合过滤查询时需要使用 FilterGroup。
- * FilterGroup 的value 必须是[OR]或者[AND]开头, 多级需要用点.分隔。 (注: 暂时不支持多级)
+ * 当需要使用OR或AND OR组合过滤查询时需要使用 FilterOrs、FilterGroup。
* 示例一: * *
* *
+ * @FilterOrs({"g1"})
  * public class TestFilterBean implements FilterBean {
  *
  *      private int id;
  *
- *      @FilterGroup("[OR]g1")
+ *      @FilterGroup("g1")
  *      private String desc;
  *
- *      @FilterGroup("[OR]g1")
+ *      @FilterGroup("g1")
  *      private String name;
  * }
  * 
@@ -40,22 +39,23 @@ import java.lang.annotation.*; *
* *
+ * @FilterOrs({"g1","subg2"})
  * public class TestFilterBean implements FilterBean {
  *
  *      private int id;
  *
- *      @FilterGroup("[OR]g1.[AND]subg1")
+ *      @FilterGroup("g1.subg1")
  *      @FilterColumn(express = LIKE)
  *      private String desc;
  *
- *      @FilterGroup("[OR]g1.[AND]subg1")
+ *      @FilterGroup("g1.subg1")
  *      @FilterColumn(express = LIKE)
  *      private String name;
  *
- *      @FilterGroup("[OR]g1.[OR]subg2")
+ *      @FilterGroup("g1.subg2")
  *      private int age;
  *
- *      @FilterGroup("[OR]g1.[OR]subg2")
+ *      @FilterGroup("g1.subg2")
  *      private int birthday;
  * }
  * 
@@ -63,14 +63,13 @@ import java.lang.annotation.*; *
* * 转换的SQL语句为: WHERE id = ? AND ((desc LIKE ? AND name LIKE ?) OR (age = ? OR birthday = ?))
- * 因为默认是AND关系, @FilterGroup("") 等价于 @FilterGroup("[AND]")
- * 所以示例二的@FilterGroup("[OR]g1.[AND]subg1") 可以简化为 @FilterGroup("[OR]g1.subg1")
*/ /** * 详情见: https://redkale.org * * @see org.redkale.source.FilterBean * @see org.redkale.source.FilterNode + * @see org.redkale.source.FilterOrs * @author zhangjx */ @Documented @@ -78,5 +77,5 @@ import java.lang.annotation.*; @Retention(RUNTIME) public @interface FilterGroup { - String value() default "[AND]"; + String value() default ""; } diff --git a/src/main/java/org/redkale/source/FilterNodeBean.java b/src/main/java/org/redkale/source/FilterNodeBean.java index 23e80d270..07a79e39d 100644 --- a/src/main/java/org/redkale/source/FilterNodeBean.java +++ b/src/main/java/org/redkale/source/FilterNodeBean.java @@ -5,14 +5,13 @@ */ package org.redkale.source; -import static org.redkale.source.FilterExpress.*; - import java.io.Serializable; import java.lang.reflect.*; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.locks.ReentrantLock; import org.redkale.persistence.Transient; +import static org.redkale.source.FilterExpress.*; import org.redkale.util.*; /** @@ -105,10 +104,6 @@ public final class FilterNodeBean implements Comparable implements Comparable FilterNodeBean createFilterNodeBean(final Class clazz) { final Set fields = new HashSet<>(); final Map nodemap = new LinkedHashMap(); - Class cltmp = clazz; + Set orItems = new HashSet<>(); + // 读取FilterOrs + Class cltmp = clazz; + do { + FilterOrs ors = cltmp.getAnnotation(FilterOrs.class); + if (ors != null) { + orItems.addAll(List.of(ors.value())); + } + } while ((cltmp = cltmp.getSuperclass()) != Object.class); + // 读取FilterGroup + cltmp = clazz; do { for (final Field field : cltmp.getDeclaredFields()) { if (Modifier.isStatic(field.getModifiers())) { @@ -267,27 +272,20 @@ public final class FilterNodeBean implements Comparable implements Comparable { String[] keys = k.split("\\."); LinkNode link = linkes.get(keys[0]); + boolean or = orItems.contains(keys[0]) || keys[0].contains("[OR]"); if (link == null) { - linkes.put(keys[0], new LinkNode(k, v)); + linkes.put(keys[0], new LinkNode(keys, or, 0, v)); } else { - link.put(keys, 0, v); + link.put(keys, or, 0, v); } }); FilterNodeBean rs = null; @@ -338,17 +337,10 @@ public final class FilterNodeBean implements Comparable nexts = new LinkedHashMap<>(); - public LinkNode(String keyString, FilterNodeBean node) { - String[] keys = keyString.split("\\."); - this.key = keys[0]; - this.or = this.key.contains("[OR]"); - put(keys, 0, node); - } - - public LinkNode(String[] keyStrings, int pos, FilterNodeBean node) { + public LinkNode(String[] keyStrings, boolean or, int pos, FilterNodeBean node) { this.key = keyStrings[pos]; - this.or = this.key.contains("[OR]"); - put(keyStrings, pos, node); + this.or = or; + put(keyStrings, or, pos, node); } public FilterNodeBean createFilterNodeBean() { @@ -366,16 +358,16 @@ public final class FilterNodeBean implements ComparableOR关系 + * + * 详情见: https://redkale.org + * + * @see org.redkale.source.FilterBean + * @see org.redkale.source.FilterNode + * @see org.redkale.source.FilterGroup + * @author zhangjx + * @since 2.8.0 + */ +@Documented +@Target({ElementType.TYPE}) +@Retention(RUNTIME) +public @interface FilterOrs { + /** + * OR 关系的组名 + * + * @return + */ + String[] value(); +} diff --git a/src/main/java/org/redkale/util/Copier.java b/src/main/java/org/redkale/util/Copier.java index 158b8478e..91d7eab22 100644 --- a/src/main/java/org/redkale/util/Copier.java +++ b/src/main/java/org/redkale/util/Copier.java @@ -3,15 +3,14 @@ */ package org.redkale.util; -import static org.redkale.asm.ClassWriter.COMPUTE_FRAMES; -import static org.redkale.asm.Opcodes.*; - import java.lang.reflect.*; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.function.*; import java.util.stream.Collectors; import org.redkale.asm.*; +import static org.redkale.asm.ClassWriter.COMPUTE_FRAMES; +import static org.redkale.asm.Opcodes.*; import org.redkale.asm.Type; /** @@ -26,13 +25,19 @@ import org.redkale.asm.Type; */ public interface Copier extends BiFunction { - /** 是否跳过值为null的字段 */ + /** + * 是否跳过值为null的字段 + */ public static final int OPTION_SKIP_NULL_VALUE = 1 << 1; // 2 - /** 是否跳过值为空字符串的字段 */ + /** + * 是否跳过值为空字符串的字段 + */ public static final int OPTION_SKIP_EMPTY_STRING = 1 << 2; // 4 - /** 同名字段类型强制转换 */ + /** + * 同名字段类型强制转换 + */ public static final int OPTION_ALLOW_TYPE_CAST = 1 << 3; // 8 /** diff --git a/src/test/java/org/redkale/test/source/FilterNodeTest.java b/src/test/java/org/redkale/test/source/FilterNodeTest.java index d0083e0aa..7196374a9 100644 --- a/src/test/java/org/redkale/test/source/FilterNodeTest.java +++ b/src/test/java/org/redkale/test/source/FilterNodeTest.java @@ -5,8 +5,6 @@ */ package org.redkale.test.source; -import static org.redkale.source.FilterExpress.*; - import java.lang.reflect.Method; import java.util.*; import java.util.concurrent.CompletableFuture; @@ -18,6 +16,7 @@ import org.redkale.persistence.Entity; import org.redkale.persistence.Id; import org.redkale.persistence.Transient; import org.redkale.source.*; +import static org.redkale.source.FilterExpress.*; /** @author zhangjx */ public class FilterNodeTest { @@ -184,28 +183,29 @@ public class FilterNodeTest { System.out.println("bean.sheet = " + carEntity.getCache().querySheet(null, new Flipper(), beanNode)); } + @FilterOrs({"r", "c"}) public static class CarTestBean implements FilterBean { - @FilterGroup("[OR].[AND]a") + @FilterGroup("r.a") @FilterColumn(express = GT) @Transient public long carid; - @FilterGroup("[OR].[AND]a.[OR]c") + @FilterGroup("r.a.c") @FilterColumn(express = LIKE) @FilterJoinColumn( table = UserTestTable.class, columns = {"userid", "username"}) public String username; - @FilterGroup("[OR].[AND]a.[OR]c") + @FilterGroup("r.a.c") @FilterColumn(express = GT) @FilterJoinColumn( table = UserTestTable.class, columns = {"userid", "username"}) public long createtime; - @FilterGroup("[OR]") + @FilterGroup("r") @FilterColumn(express = LIKE) @FilterJoinColumn( table = CarTypeTable.class,