增加FilterOrs功能
This commit is contained in:
@@ -46,7 +46,7 @@ public class EntityBuilder<T> {
|
||||
// key:类字段名, value:数据库字段名
|
||||
// 只有field.name 与 Column.name不同才存放在aliasmap里.
|
||||
@Nullable
|
||||
private final Map<String, String> aliasmap;
|
||||
private final Map<String, String> aliasMap;
|
||||
|
||||
// Entity构建器参数Attribute, 数组个数与constructorParameters相同
|
||||
@Nullable
|
||||
@@ -71,7 +71,7 @@ public class EntityBuilder<T> {
|
||||
EntityBuilder(
|
||||
Class<T> type,
|
||||
Creator<T> creator,
|
||||
Map<String, String> aliasmap,
|
||||
Map<String, String> aliasMap,
|
||||
String[] constructorParameters,
|
||||
Attribute<T, Serializable>[] constructorAttributes,
|
||||
Attribute<T, Serializable>[] unconstructorAttributes,
|
||||
@@ -79,7 +79,7 @@ public class EntityBuilder<T> {
|
||||
Attribute<T, Serializable>[] 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<T> {
|
||||
}
|
||||
}
|
||||
} 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<T> {
|
||||
* @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<T> {
|
||||
*/
|
||||
@ConvertDisabled
|
||||
public boolean isNoAlias() {
|
||||
return this.aliasmap == null;
|
||||
return this.aliasMap == null;
|
||||
}
|
||||
|
||||
@ConvertDisabled
|
||||
|
||||
@@ -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.*;
|
||||
|
||||
/**
|
||||
* 过滤字段标记
|
||||
*
|
||||
|
||||
@@ -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关系。 <br>
|
||||
* 当需要使用OR或AND OR组合过滤查询时需要使用 FilterGroup。 <br>
|
||||
* FilterGroup 的value 必须是[OR]或者[AND]开头, 多级需要用点.分隔。 (注: 暂时不支持多级) <br>
|
||||
* 当需要使用OR或AND OR组合过滤查询时需要使用 FilterOrs、FilterGroup。 <br>
|
||||
* 示例一:
|
||||
*
|
||||
* <blockquote>
|
||||
*
|
||||
* <pre>
|
||||
* @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;
|
||||
* }
|
||||
* </pre>
|
||||
@@ -40,22 +39,23 @@ import java.lang.annotation.*;
|
||||
* <blockquote>
|
||||
*
|
||||
* <pre>
|
||||
* @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;
|
||||
* }
|
||||
* </pre>
|
||||
@@ -63,14 +63,13 @@ import java.lang.annotation.*;
|
||||
* </blockquote>
|
||||
*
|
||||
* 转换的SQL语句为: WHERE id = ? AND ((desc LIKE ? AND name LIKE ?) OR (age = ? OR birthday = ?)) <br>
|
||||
* 因为默认是AND关系, @FilterGroup("") 等价于 @FilterGroup("[AND]") <br>
|
||||
* 所以示例二的@FilterGroup("[OR]g1.[AND]subg1") 可以简化为 @FilterGroup("[OR]g1.subg1") <br>
|
||||
*/
|
||||
/**
|
||||
* 详情见: 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 "";
|
||||
}
|
||||
|
||||
@@ -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<T extends FilterBean> implements Comparable<Fi
|
||||
this.string = CharSequence.class.isAssignableFrom(type);
|
||||
}
|
||||
|
||||
private FilterNodeBean or(FilterNodeBean node) {
|
||||
return any(node, true);
|
||||
}
|
||||
|
||||
private FilterNodeBean and(FilterNodeBean node) {
|
||||
return any(node, false);
|
||||
}
|
||||
@@ -203,7 +198,17 @@ public final class FilterNodeBean<T extends FilterBean> implements Comparable<Fi
|
||||
private static <T extends FilterBean> FilterNodeBean createFilterNodeBean(final Class<T> clazz) {
|
||||
final Set<String> fields = new HashSet<>();
|
||||
final Map<String, FilterNodeBean> nodemap = new LinkedHashMap();
|
||||
Class cltmp = clazz;
|
||||
Set<String> 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<T extends FilterBean> implements Comparable<Fi
|
||||
groups[i] = refs[i].value();
|
||||
}
|
||||
if (groups.length == 0) {
|
||||
groups = new String[] {"[AND]"};
|
||||
groups = new String[] {""};
|
||||
}
|
||||
for (String key : groups) {
|
||||
if (!key.startsWith("[AND]") && !key.startsWith("[OR]")) {
|
||||
throw new SourceException(field + "'s FilterGroup.value(" + key
|
||||
+ ") illegal, must be [AND] or [OR] startsWith");
|
||||
}
|
||||
FilterNodeBean node = nodemap.get(key);
|
||||
if (node == null) {
|
||||
nodemap.put(key, nodeBean);
|
||||
} else if (nodeBean.joinClass == null && node.joinClass != null) { // 非joinNode 关联 joinNode
|
||||
nodemap.put(
|
||||
key,
|
||||
nodeBean.any(
|
||||
node,
|
||||
key.substring(key.lastIndexOf('.') + 1)
|
||||
.contains("[OR]")));
|
||||
String subKey = key.substring(key.lastIndexOf('.') + 1);
|
||||
boolean or = orItems.contains(subKey) || subKey.contains("[OR]");
|
||||
nodemap.put(key, nodeBean.any(node, or));
|
||||
} else {
|
||||
node.any(
|
||||
nodeBean,
|
||||
key.substring(key.lastIndexOf('.') + 1).contains("[OR]"));
|
||||
String subKey = key.substring(key.lastIndexOf('.') + 1);
|
||||
boolean or = orItems.contains(subKey) || subKey.contains("[OR]");
|
||||
node.any(nodeBean, or);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -297,10 +295,11 @@ public final class FilterNodeBean<T extends FilterBean> implements Comparable<Fi
|
||||
nodemap.forEach((k, v) -> {
|
||||
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<T extends FilterBean> implements Comparable<Fi
|
||||
|
||||
public final Map<String, LinkNode> 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<T extends FilterBean> implements Comparable<Fi
|
||||
return node;
|
||||
}
|
||||
|
||||
public final void put(final String[] keys, int pos, final FilterNodeBean node) {
|
||||
public final void put(final String[] keys, boolean or, int pos, final FilterNodeBean node) {
|
||||
if (keys.length == pos + 1 && this.key.equals(keys[pos])) {
|
||||
this.beans.add(node);
|
||||
return;
|
||||
}
|
||||
LinkNode link = nexts.get(keys[pos + 1]);
|
||||
if (link == null) {
|
||||
nexts.put(keys[pos + 1], new LinkNode(keys, pos + 1, node));
|
||||
nexts.put(keys[pos + 1], new LinkNode(keys, or, pos + 1, node));
|
||||
} else {
|
||||
link.put(keys, pos + 1, node);
|
||||
link.put(keys, or, pos + 1, node);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
34
src/main/java/org/redkale/source/FilterOrs.java
Normal file
34
src/main/java/org/redkale/source/FilterOrs.java
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
|
||||
*/
|
||||
|
||||
package org.redkale.source;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* 设置 {@link org.redkale.source.FilterGroup}的<b>OR</b>关系
|
||||
*
|
||||
* 详情见: 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();
|
||||
}
|
||||
@@ -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<S, D> extends BiFunction<S, D, D> {
|
||||
|
||||
/** 是否跳过值为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
|
||||
|
||||
/**
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user