filter 改版中……
This commit is contained in:
@@ -641,7 +641,9 @@ public final class DataDefaultSource implements DataSource, Nameable {
|
||||
private <T> void delete(final Connection conn, final EntityInfo<T> info, final FilterNode node) {
|
||||
try {
|
||||
if (!info.isVirtualEntity()) {
|
||||
String sql = "DELETE FROM " + info.getTable() + node.createFilterSQLExpress(info, null);
|
||||
CharSequence join = node.createSQLJoin(info);
|
||||
CharSequence where = node.createSQLExpress(info, null);
|
||||
String sql = "DELETE FROM " + info.getTable() + (join == null ? "" : join) + ((where == null || where.length() == 0) ? "" : (" WHERE " + where));
|
||||
if (debug.get()) logger.finest(info.getType().getSimpleName() + " delete sql=" + sql);
|
||||
final Statement stmt = conn.createStatement();
|
||||
stmt.execute(sql);
|
||||
@@ -1081,12 +1083,14 @@ public final class DataDefaultSource implements DataSource, Nameable {
|
||||
if (node == null && bean != null) node = loadFilterBeanNode(bean.getClass());
|
||||
final EntityCache<T> cache = info.getCache();
|
||||
if (cache != null && (info.isVirtualEntity() || cache.isFullLoaded())) {
|
||||
if (node == null || node.isJoinAllCached()) {
|
||||
if (node == null || node.isCacheUseable()) {
|
||||
return cache.getNumberResult(reckon, column, node, bean);
|
||||
}
|
||||
}
|
||||
final CharSequence join = node == null ? null : node.createSQLJoin(info);
|
||||
final CharSequence where = node == null ? null : node.createSQLExpress(info, bean);
|
||||
final String sql = "SELECT " + reckon.getColumn((column == null || column.isEmpty() ? "*" : ("a." + column))) + " FROM " + info.getTable() + " a"
|
||||
+ (node == null ? "" : node.createFilterSQLExpress(info, bean));
|
||||
+ (join == null ? "" : join) + ((where == null || where.length() == 0) ? "" : (" WHERE " + where));
|
||||
if (debug.get() && info.isLoggable(Level.FINEST)) logger.finest(entityClass.getSimpleName() + " single sql=" + sql);
|
||||
final PreparedStatement prestmt = conn.prepareStatement(sql);
|
||||
Number rs = null;
|
||||
@@ -1127,13 +1131,15 @@ public final class DataDefaultSource implements DataSource, Nameable {
|
||||
if (node == null && bean != null) node = loadFilterBeanNode(bean.getClass());
|
||||
final EntityCache cache = info.getCache();
|
||||
if (cache != null && (info.isVirtualEntity() || cache.isFullLoaded())) {
|
||||
if (node == null || node.isJoinAllCached()) {
|
||||
if (node == null || node.isCacheUseable()) {
|
||||
return cache.getMapResult(keyColumn, reckon, reckonColumn, node, bean);
|
||||
}
|
||||
}
|
||||
final String sqlkey = info.getSQLColumn(keyColumn);
|
||||
final CharSequence join = node == null ? null : node.createSQLJoin(info);
|
||||
final CharSequence where = node == null ? null : node.createSQLExpress(info, bean);
|
||||
final String sql = "SELECT a." + sqlkey + ", " + reckon.getColumn((reckonColumn == null || reckonColumn.isEmpty() ? "*" : ("a." + reckonColumn)))
|
||||
+ " FROM " + info.getTable() + " a" + (node == null ? "" : node.createFilterSQLExpress(info, bean)) + " GROUP BY a." + sqlkey;
|
||||
+ " FROM " + info.getTable() + " a" + (join == null ? "" : join) + ((where == null || where.length() == 0) ? "" : (" WHERE " + where)) + " GROUP BY a." + sqlkey;
|
||||
if (debug.get() && info.isLoggable(Level.FINEST)) logger.finest(entityClass.getSimpleName() + " single sql=" + sql);
|
||||
final PreparedStatement prestmt = conn.prepareStatement(sql);
|
||||
Map<K, V> rs = new LinkedHashMap<>();
|
||||
@@ -1433,8 +1439,8 @@ public final class DataDefaultSource implements DataSource, Nameable {
|
||||
final EntityCache<T> cache = info.getCache();
|
||||
if (node == null && bean != null) node = loadFilterBeanNode(bean.getClass());
|
||||
if (readcache && cache != null) {
|
||||
if (node == null || node.isJoinAllCached()) {
|
||||
if (debug.get() && info.isLoggable(Level.FINEST)) logger.finest(clazz.getSimpleName() + " cache query predicate = " + (node == null ? null : node.createFilterPredicate(info, bean)));
|
||||
if (node == null || node.isCacheUseable()) {
|
||||
if (debug.get() && info.isLoggable(Level.FINEST)) logger.finest(clazz.getSimpleName() + " cache query predicate = " + (node == null ? null : node.createPredicate(cache, bean)));
|
||||
Sheet<T> sheet = cache.querySheet(needtotal, selects, flipper, node, bean);
|
||||
if (!sheet.isEmpty() || info.isVirtualEntity() || cache.isFullLoaded()) return sheet;
|
||||
}
|
||||
@@ -1443,8 +1449,10 @@ public final class DataDefaultSource implements DataSource, Nameable {
|
||||
try {
|
||||
final SelectColumn sels = selects;
|
||||
final List<T> list = new ArrayList();
|
||||
final String sql = "SELECT a.* FROM " + info.getTable() + " a"
|
||||
+ (node == null ? "" : node.createFilterSQLExpress(info, bean)) + createFilterSQLOrderBy(info, flipper);
|
||||
final CharSequence join = node == null ? null : node.createSQLJoin(info);
|
||||
final CharSequence where = node == null ? null : node.createSQLExpress(info, bean);
|
||||
final String sql = "SELECT a.* FROM " + info.getTable() + " a" + (join == null ? "" : join)
|
||||
+ ((where == null || where.length() == 0) ? "" : (" WHERE " + where)) + info.createSQLOrderby(flipper);
|
||||
if (debug.get() && info.isLoggable(Level.FINEST))
|
||||
logger.finest(clazz.getSimpleName() + " query sql=" + sql + (flipper == null ? "" : (" LIMIT " + flipper.index() + "," + flipper.getSize())));
|
||||
final PreparedStatement ps = conn.prepareStatement(sql, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
|
||||
|
||||
@@ -25,81 +25,11 @@ import java.util.stream.*;
|
||||
*/
|
||||
public final class EntityCache<T> {
|
||||
|
||||
private static class UniqueSequence implements Serializable {
|
||||
|
||||
private final Serializable[] value;
|
||||
|
||||
public UniqueSequence(Serializable[] val) {
|
||||
this.value = val;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Arrays.deepHashCode(this.value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null) return false;
|
||||
if (getClass() != obj.getClass()) return false;
|
||||
final UniqueSequence other = (UniqueSequence) obj;
|
||||
if (value.length != other.value.length) return false;
|
||||
for (int i = 0; i < value.length; i++) {
|
||||
if (!value[i].equals(other.value[i])) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static interface UniqueAttribute<T> extends Predicate<FilterNode> {
|
||||
|
||||
public Serializable getValue(T bean);
|
||||
|
||||
@Override
|
||||
public boolean test(FilterNode node);
|
||||
|
||||
public static <T> UniqueAttribute<T> create(final Attribute<T, Serializable>[] attributes) {
|
||||
if (attributes.length == 1) {
|
||||
final Attribute<T, Serializable> attribute = attributes[0];
|
||||
return new UniqueAttribute<T>() {
|
||||
|
||||
@Override
|
||||
public Serializable getValue(T bean) {
|
||||
return attribute.get(bean);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(FilterNode node) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
} else {
|
||||
return new UniqueAttribute<T>() {
|
||||
|
||||
@Override
|
||||
public Serializable getValue(T bean) {
|
||||
final Serializable[] rs = new Serializable[attributes.length];
|
||||
for (int i = 0; i < rs.length; i++) {
|
||||
rs[i] = attributes[i].get(bean);
|
||||
}
|
||||
return new UniqueSequence(rs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(FilterNode node) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final Logger logger = Logger.getLogger(EntityCache.class.getName());
|
||||
|
||||
private final ConcurrentHashMap<Serializable, T> map = new ConcurrentHashMap();
|
||||
|
||||
private final CopyOnWriteArrayList<T> list = new CopyOnWriteArrayList(); // CopyOnWriteArrayList 插入慢、查询快; 10w数据插入需要3.2秒; ConcurrentLinkedQueue 插入快、查询慢;10w数据查询需要 0.062秒, 查询慢40%;
|
||||
private final Collection<T> list = new CopyOnWriteArrayList(); // CopyOnWriteArrayList 插入慢、查询快; 10w数据插入需要3.2秒; ConcurrentLinkedQueue 插入快、查询慢;10w数据查询需要 0.062秒, 查询慢40%;
|
||||
|
||||
private final HashMap<UniqueAttribute<T>, ConcurrentHashMap<Serializable, Collection<T>>> uniques = new HashMap<>();
|
||||
|
||||
@@ -180,14 +110,19 @@ public final class EntityCache<T> {
|
||||
}
|
||||
|
||||
public boolean exists(final Predicate<T> filter) {
|
||||
return (filter != null) && listStream().filter(filter).findFirst().isPresent();
|
||||
return (filter != null) && this.list.stream().filter(filter).findFirst().isPresent();
|
||||
}
|
||||
|
||||
public <K, V> Map<Serializable, Number> getMapResult(final String keyColumn, final Reckon reckon, final String reckonColumn, final FilterNode node, final FilterBean bean) {
|
||||
public <K, V> Map<Serializable, Number> getMapResult(final String keyColumn, final Reckon reckon, final String reckonColumn, final FilterNode node) {
|
||||
return getMapResult(keyColumn, reckon, reckonColumn, node, null);
|
||||
}
|
||||
|
||||
public <K, V> Map<Serializable, Number> getMapResult(final String keyColumn, final Reckon reckon, final String reckonColumn, FilterNode node, final FilterBean bean) {
|
||||
if (node == null && bean != null) node = FilterBeanNode.load(bean.getClass());
|
||||
final Attribute<T, Serializable> keyAttr = info.getAttribute(keyColumn);
|
||||
final Predicate filter = node == null ? null : node.createFilterPredicate(this.info, bean);
|
||||
final Predicate filter = node == null ? null : node.createPredicate(this, bean);
|
||||
final Attribute reckonAttr = reckonColumn == null ? null : info.getAttribute(reckonColumn);
|
||||
Stream<T> stream = listStream();
|
||||
Stream<T> stream = this.list.stream();
|
||||
if (filter != null) stream = stream.filter(filter);
|
||||
Collector<T, Map, ?> collector = null;
|
||||
final Class valtype = reckonAttr == null ? null : reckonAttr.type();
|
||||
@@ -232,10 +167,15 @@ public final class EntityCache<T> {
|
||||
return rs;
|
||||
}
|
||||
|
||||
public <V> Number getNumberResult(final Reckon reckon, final String column, final FilterNode node, final FilterBean bean) {
|
||||
public <V> Number getNumberResult(final Reckon reckon, final String column, final FilterNode node) {
|
||||
return getNumberResult(reckon, column, node, null);
|
||||
}
|
||||
|
||||
public <V> Number getNumberResult(final Reckon reckon, final String column, FilterNode node, final FilterBean bean) {
|
||||
if (node == null && bean != null) node = FilterBeanNode.load(bean.getClass());
|
||||
final Attribute<T, Serializable> attr = column == null ? null : info.getAttribute(column);
|
||||
final Predicate<T> filter = node == null ? null : node.createFilterPredicate(this.info, bean);
|
||||
Stream<T> stream = listStream();
|
||||
final Predicate<T> filter = node == null ? null : node.createPredicate(this, bean);
|
||||
Stream<T> stream = this.list.stream();
|
||||
if (filter != null) stream = stream.filter(filter);
|
||||
switch (reckon) {
|
||||
case AVG:
|
||||
@@ -299,21 +239,30 @@ public final class EntityCache<T> {
|
||||
return -1;
|
||||
}
|
||||
|
||||
public Sheet<T> querySheet(final SelectColumn selects, final Flipper flipper, final FilterNode node) {
|
||||
return querySheet(selects, flipper, node, null);
|
||||
}
|
||||
|
||||
public Sheet<T> querySheet(final SelectColumn selects, final Flipper flipper, final FilterNode node, final FilterBean bean) {
|
||||
return querySheet(true, selects, flipper, node, bean);
|
||||
}
|
||||
|
||||
public Sheet<T> querySheet(final boolean needtotal, final SelectColumn selects, final Flipper flipper, final FilterNode node, final FilterBean bean) {
|
||||
final Predicate<T> filter = node == null ? null : node.createFilterPredicate(this.info, bean);
|
||||
final Comparator<T> comparator = FilterNode.createFilterComparator(this, flipper);
|
||||
public Sheet<T> querySheet(final boolean needtotal, final SelectColumn selects, final Flipper flipper, final FilterNode node) {
|
||||
return querySheet(needtotal, selects, flipper, node, null);
|
||||
}
|
||||
|
||||
public Sheet<T> querySheet(final boolean needtotal, final SelectColumn selects, final Flipper flipper, FilterNode node, final FilterBean bean) {
|
||||
if (node == null && bean != null) node = FilterBeanNode.load(bean.getClass());
|
||||
final Predicate<T> filter = node == null ? null : node.createPredicate(this, bean);
|
||||
final Comparator<T> comparator = createComparator(flipper);
|
||||
long total = 0;
|
||||
if (needtotal) {
|
||||
Stream<T> stream = listStream();
|
||||
Stream<T> stream = this.list.stream();
|
||||
if (filter != null) stream = stream.filter(filter);
|
||||
total = stream.count();
|
||||
}
|
||||
if (needtotal && total == 0) return new Sheet<>();
|
||||
Stream<T> stream = listStream();
|
||||
Stream<T> stream = this.list.stream();
|
||||
if (filter != null) stream = stream.filter(filter);
|
||||
if (comparator != null) stream = stream.sorted(comparator);
|
||||
if (flipper != null) stream = stream.skip(flipper.index()).limit(flipper.getSize());
|
||||
@@ -327,9 +276,9 @@ public final class EntityCache<T> {
|
||||
}
|
||||
} else {
|
||||
final List<Attribute<T, Serializable>> attrs = new ArrayList<>();
|
||||
for (Map.Entry<String, Attribute<T, Serializable>> en : info.attributes.entrySet()) {
|
||||
if (selects.validate(en.getKey())) attrs.add(en.getValue());
|
||||
}
|
||||
info.forEachAttribute((k, v) -> {
|
||||
if (selects.validate(k)) attrs.add(v);
|
||||
});
|
||||
Consumer<? super T> action = x -> {
|
||||
final T item = creator.create();
|
||||
for (Attribute attr : attrs) {
|
||||
@@ -371,7 +320,7 @@ public final class EntityCache<T> {
|
||||
|
||||
public Serializable[] delete(final FilterNode node) {
|
||||
if (node == null || this.list.isEmpty()) return new Serializable[0];
|
||||
Object[] rms = listStream().filter(node.createFilterPredicate(this.info, null)).toArray();
|
||||
Object[] rms = this.list.stream().filter(node.createPredicate(this, null)).toArray();
|
||||
Serializable[] ids = new Serializable[rms.length];
|
||||
int i = -1;
|
||||
for (Object o : rms) {
|
||||
@@ -453,15 +402,237 @@ public final class EntityCache<T> {
|
||||
return rs;
|
||||
}
|
||||
|
||||
private Stream<T> listStream() {
|
||||
return this.list.stream();
|
||||
public Attribute<T, Serializable> getAttribute(String fieldname) {
|
||||
return info.getAttribute(fieldname);
|
||||
}
|
||||
|
||||
protected Comparator<T> getSortComparator(String sort) {
|
||||
return this.sortComparators.get(sort);
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------------------
|
||||
protected Comparator<T> createComparator(Flipper flipper) {
|
||||
if (flipper == null || flipper.getSort() == null || flipper.getSort().isEmpty()) return null;
|
||||
final String sort = flipper.getSort();
|
||||
Comparator<T> comparator = this.sortComparators.get(sort);
|
||||
if (comparator != null) return comparator;
|
||||
for (String item : sort.split(",")) {
|
||||
if (item.trim().isEmpty()) continue;
|
||||
String[] sub = item.trim().split("\\s+");
|
||||
int pos = sub[0].indexOf('(');
|
||||
Attribute<T, Serializable> attr;
|
||||
if (pos <= 0) {
|
||||
attr = getAttribute(sub[0]);
|
||||
} else { //含SQL函数
|
||||
int pos2 = sub[0].lastIndexOf(')');
|
||||
final Attribute<T, Serializable> pattr = getAttribute(sub[0].substring(pos + 1, pos2));
|
||||
final String func = sub[0].substring(0, pos);
|
||||
if ("ABS".equalsIgnoreCase(func)) {
|
||||
if (pattr.type() == int.class || pattr.type() == Integer.class) {
|
||||
attr = new Attribute<T, Serializable>() {
|
||||
|
||||
protected void putSortComparator(String sort, Comparator<T> comparator) {
|
||||
@Override
|
||||
public Class type() {
|
||||
return pattr.type();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class declaringClass() {
|
||||
return pattr.declaringClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String field() {
|
||||
return pattr.field();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Serializable get(T obj) {
|
||||
return Math.abs(((Number) pattr.get(obj)).intValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(T obj, Serializable value) {
|
||||
pattr.set(obj, value);
|
||||
}
|
||||
};
|
||||
} else if (pattr.type() == long.class || pattr.type() == Long.class) {
|
||||
attr = new Attribute<T, Serializable>() {
|
||||
|
||||
@Override
|
||||
public Class type() {
|
||||
return pattr.type();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class declaringClass() {
|
||||
return pattr.declaringClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String field() {
|
||||
return pattr.field();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Serializable get(T obj) {
|
||||
return Math.abs(((Number) pattr.get(obj)).longValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(T obj, Serializable value) {
|
||||
pattr.set(obj, value);
|
||||
}
|
||||
};
|
||||
} else if (pattr.type() == float.class || pattr.type() == Float.class) {
|
||||
attr = new Attribute<T, Serializable>() {
|
||||
|
||||
@Override
|
||||
public Class type() {
|
||||
return pattr.type();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class declaringClass() {
|
||||
return pattr.declaringClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String field() {
|
||||
return pattr.field();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Serializable get(T obj) {
|
||||
return Math.abs(((Number) pattr.get(obj)).floatValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(T obj, Serializable value) {
|
||||
pattr.set(obj, value);
|
||||
}
|
||||
};
|
||||
} else if (pattr.type() == double.class || pattr.type() == Double.class) {
|
||||
attr = new Attribute<T, Serializable>() {
|
||||
|
||||
@Override
|
||||
public Class type() {
|
||||
return pattr.type();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class declaringClass() {
|
||||
return pattr.declaringClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String field() {
|
||||
return pattr.field();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Serializable get(T obj) {
|
||||
return Math.abs(((Number) pattr.get(obj)).doubleValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(T obj, Serializable value) {
|
||||
pattr.set(obj, value);
|
||||
}
|
||||
};
|
||||
} else {
|
||||
throw new RuntimeException("Flipper not supported sort illegal type by ABS (" + flipper.getSort() + ")");
|
||||
}
|
||||
} else if (func.isEmpty()) {
|
||||
attr = pattr;
|
||||
} else {
|
||||
throw new RuntimeException("Flipper not supported sort illegal function (" + flipper.getSort() + ")");
|
||||
}
|
||||
}
|
||||
Comparator<T> c = (sub.length > 1 && sub[1].equalsIgnoreCase("DESC")) ? (T o1, T o2) -> {
|
||||
Comparable c1 = (Comparable) attr.get(o1);
|
||||
Comparable c2 = (Comparable) attr.get(o2);
|
||||
return c2 == null ? -1 : c2.compareTo(c1);
|
||||
} : (T o1, T o2) -> {
|
||||
Comparable c1 = (Comparable) attr.get(o1);
|
||||
Comparable c2 = (Comparable) attr.get(o2);
|
||||
return c1 == null ? -1 : c1.compareTo(c2);
|
||||
};
|
||||
|
||||
if (comparator == null) {
|
||||
comparator = c;
|
||||
} else {
|
||||
comparator = comparator.thenComparing(c);
|
||||
}
|
||||
}
|
||||
this.sortComparators.put(sort, comparator);
|
||||
return comparator;
|
||||
}
|
||||
|
||||
private static class UniqueSequence implements Serializable {
|
||||
|
||||
private final Serializable[] value;
|
||||
|
||||
public UniqueSequence(Serializable[] val) {
|
||||
this.value = val;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Arrays.deepHashCode(this.value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null) return false;
|
||||
if (getClass() != obj.getClass()) return false;
|
||||
final UniqueSequence other = (UniqueSequence) obj;
|
||||
if (value.length != other.value.length) return false;
|
||||
for (int i = 0; i < value.length; i++) {
|
||||
if (!value[i].equals(other.value[i])) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static interface UniqueAttribute<T> extends Predicate<FilterNode> {
|
||||
|
||||
public Serializable getValue(T bean);
|
||||
|
||||
@Override
|
||||
public boolean test(FilterNode node);
|
||||
|
||||
public static <T> UniqueAttribute<T> create(final Attribute<T, Serializable>[] attributes) {
|
||||
if (attributes.length == 1) {
|
||||
final Attribute<T, Serializable> attribute = attributes[0];
|
||||
return new UniqueAttribute<T>() {
|
||||
|
||||
@Override
|
||||
public Serializable getValue(T bean) {
|
||||
return attribute.get(bean);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(FilterNode node) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
} else {
|
||||
return new UniqueAttribute<T>() {
|
||||
|
||||
@Override
|
||||
public Serializable getValue(T bean) {
|
||||
final Serializable[] rs = new Serializable[attributes.length];
|
||||
for (int i = 0; i < rs.length; i++) {
|
||||
rs[i] = attributes[i].get(bean);
|
||||
}
|
||||
return new UniqueSequence(rs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(FilterNode node) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ public final class EntityInfo<T> {
|
||||
|
||||
//key是field的name, 不是sql字段。
|
||||
//存放所有与数据库对应的字段, 包括主键
|
||||
final Map<String, Attribute<T, Serializable>> attributes = new HashMap<>();
|
||||
private final HashMap<String, Attribute<T, Serializable>> attributes = new HashMap<>();
|
||||
|
||||
//key是field的name, value是Column的别名,即数据库表的字段名
|
||||
//只有field.name 与 Column.name不同才存放在aliasmap里.
|
||||
@@ -93,10 +93,12 @@ public final class EntityInfo<T> {
|
||||
synchronized (entityInfos) {
|
||||
rs = entityInfos.get(clazz);
|
||||
if (rs == null) {
|
||||
if (nodeid < 0) throw new IllegalArgumentException("nodeid(" + nodeid + ") is illegal");
|
||||
rs = new EntityInfo(clazz, nodeid, cacheForbidden);
|
||||
entityInfos.put(clazz, rs);
|
||||
AutoLoad auto = clazz.getAnnotation(AutoLoad.class);
|
||||
if (rs.cache != null && auto != null && auto.value() && fullloader != null) {
|
||||
if (rs.cache != null && auto != null && auto.value()) {
|
||||
if (fullloader == null) throw new IllegalArgumentException(clazz.getName() + " auto loader is illegal");
|
||||
rs.cache.fullLoad(fullloader.apply(clazz));
|
||||
}
|
||||
}
|
||||
@@ -107,7 +109,7 @@ public final class EntityInfo<T> {
|
||||
private EntityInfo(Class<T> type, int nodeid, final boolean cacheForbidden) {
|
||||
this.type = type;
|
||||
//---------------------------------------------
|
||||
this.nodeid = nodeid;
|
||||
this.nodeid = nodeid >= 0 ? nodeid : 0;
|
||||
DistributeGenerator.DistributeTables dt = type.getAnnotation(DistributeGenerator.DistributeTables.class);
|
||||
this.distributeTables = dt == null ? null : dt.value();
|
||||
|
||||
@@ -267,7 +269,12 @@ public final class EntityInfo<T> {
|
||||
return this.primary;
|
||||
}
|
||||
|
||||
public void forEachAttribute(BiConsumer<String, Attribute<T, Serializable>> action) {
|
||||
this.attributes.forEach(action);
|
||||
}
|
||||
|
||||
public Attribute<T, Serializable> getAttribute(String fieldname) {
|
||||
if (fieldname == null) return null;
|
||||
return this.attributes.get(fieldname);
|
||||
}
|
||||
|
||||
@@ -279,12 +286,32 @@ public final class EntityInfo<T> {
|
||||
return this.aliasmap == null;
|
||||
}
|
||||
|
||||
public String getSortOrderbySql(String sort) {
|
||||
return this.sortOrderbySqls.get(sort);
|
||||
}
|
||||
|
||||
protected void putSortOrderbySql(String sort, String sql) {
|
||||
protected String createSQLOrderby(Flipper flipper) {
|
||||
if (flipper == null || flipper.getSort() == null || flipper.getSort().isEmpty()) return "";
|
||||
final String sort = flipper.getSort();
|
||||
String sql = this.sortOrderbySqls.get(sort);
|
||||
if (sql != null) return sql;
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append(" ORDER BY ");
|
||||
if (isNoAlias()) {
|
||||
sb.append(sort);
|
||||
} else {
|
||||
boolean flag = false;
|
||||
for (String item : sort.split(",")) {
|
||||
if (item.isEmpty()) continue;
|
||||
String[] sub = item.split("\\s+");
|
||||
if (flag) sb.append(',');
|
||||
if (sub.length < 2 || sub[1].equalsIgnoreCase("ASC")) {
|
||||
sb.append("a.").append(getSQLColumn(sub[0])).append(" ASC");
|
||||
} else {
|
||||
sb.append("a.").append(getSQLColumn(sub[0])).append(" DESC");
|
||||
}
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
sql = sb.toString();
|
||||
this.sortOrderbySqls.put(sort, sql);
|
||||
return sql;
|
||||
}
|
||||
|
||||
//根据field字段名获取数据库对应的字段名
|
||||
|
||||
@@ -26,6 +26,10 @@ final class FilterBeanNode extends FilterNode {
|
||||
|
||||
private static final ConcurrentHashMap<Class, FilterBeanNode> beanodes = new ConcurrentHashMap<>();
|
||||
|
||||
public static <T extends FilterBean> FilterBeanNode load(Class<T> clazz) {
|
||||
return load(clazz, -1, true, null);
|
||||
}
|
||||
|
||||
public static <T extends FilterBean> FilterBeanNode load(Class<T> clazz, final int nodeid, final boolean cacheForbidden,
|
||||
Function<Class, List> fullloader) {
|
||||
FilterBeanNode rs = beanodes.get(clazz);
|
||||
@@ -55,17 +59,19 @@ final class FilterBeanNode extends FilterNode {
|
||||
if (field.getAnnotation(Ignore.class) != null) continue;
|
||||
if (field.getAnnotation(Transient.class) != null) continue;
|
||||
|
||||
final boolean pubmod = Modifier.isPublic(field.getModifiers());
|
||||
|
||||
char[] chars = field.getName().toCharArray();
|
||||
chars[0] = Character.toUpperCase(chars[0]);
|
||||
final Class t = field.getType();
|
||||
Method getter;
|
||||
Method getter = null;
|
||||
try {
|
||||
getter = cltmp.getMethod(((t == boolean.class || t == Boolean.class) ? "is" : "get") + new String(chars));
|
||||
} catch (Exception ex) {
|
||||
continue;
|
||||
if (!pubmod) continue;
|
||||
}
|
||||
fields.add(field.getName());
|
||||
FilterBeanNode newnode = new FilterBeanNode(field.getName(), true, Attribute.create(getter, null));
|
||||
FilterBeanNode newnode = new FilterBeanNode(field.getName(), true, pubmod ? Attribute.create(field) : Attribute.create(getter, null));
|
||||
newnode.setField(field);
|
||||
//------------------------------------
|
||||
{
|
||||
@@ -163,7 +169,7 @@ final class FilterBeanNode extends FilterNode {
|
||||
|
||||
protected FilterBeanNode(String col, boolean sign, Attribute beanAttr) {
|
||||
this.column = col;
|
||||
this.signand = sign;
|
||||
this.and = sign;
|
||||
this.beanAttribute = beanAttr;
|
||||
}
|
||||
|
||||
@@ -195,7 +201,7 @@ final class FilterBeanNode extends FilterNode {
|
||||
|
||||
@Override
|
||||
protected void append(FilterNode node, boolean sign) {
|
||||
FilterBeanNode newnode = new FilterBeanNode(this.column, this.signand, this.beanAttribute);
|
||||
FilterBeanNode newnode = new FilterBeanNode(this.column, this.and, this.beanAttribute);
|
||||
newnode.express = this.express;
|
||||
newnode.nodes = this.nodes;
|
||||
newnode.foreignEntity = this.foreignEntity;
|
||||
@@ -211,7 +217,7 @@ final class FilterBeanNode extends FilterNode {
|
||||
this.nodes = new FilterNode[]{newnode};
|
||||
this.column = node.column;
|
||||
this.express = node.express;
|
||||
this.signand = sign;
|
||||
this.and = sign;
|
||||
this.setValue(node.getValue());
|
||||
if (node instanceof FilterBeanNode) {
|
||||
FilterBeanNode beanNode = ((FilterBeanNode) node);
|
||||
@@ -230,29 +236,27 @@ final class FilterBeanNode extends FilterNode {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T> StringBuilder createFilterSQLExpress(final boolean first, final EntityInfo<T> info, FilterBean bean) {
|
||||
if (joinSQL == null || !first) return super.createFilterSQLExpress(first, info, bean);
|
||||
StringBuilder sb = super.createFilterSQLExpress(first, info, bean);
|
||||
if (joinSQL == null) return sb;
|
||||
return new StringBuilder(sb.length() + joinSQL.length()).append(joinSQL).append(sb);
|
||||
protected <T> CharSequence createSQLJoin(final EntityInfo<T> info) {
|
||||
if (joinSQL == null) return null;
|
||||
return new StringBuilder(joinSQL);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected <T> Predicate<T> createFilterPredicate(final EntityInfo<T> info, FilterBean bean) {
|
||||
//if ((this.joinSQL == null && first) || this.foreignEntity == null) return super.createFilterPredicate(info, bean);
|
||||
if (this.foreignEntity == null) return super.createFilterPredicate(info, bean);
|
||||
protected <T> Predicate<T> createPredicate(final EntityCache<T> cache, FilterBean bean) {
|
||||
if (this.foreignEntity == null) return super.createPredicate(cache, bean);
|
||||
final Map<EntityInfo, Predicate> foreign = new HashMap<>();
|
||||
Predicate<T> result = null;
|
||||
putForeignPredicate(foreign, bean);
|
||||
putForeignPredicate(cache, foreign, bean);
|
||||
if (this.nodes != null) {
|
||||
for (FilterNode n : this.nodes) {
|
||||
FilterBeanNode node = (FilterBeanNode) n;
|
||||
if (node.foreignEntity == null) {
|
||||
Predicate<T> f = node.createFilterPredicate(info, bean);
|
||||
Predicate<T> f = node.createPredicate(cache, bean);
|
||||
if (f == null) continue;
|
||||
final Predicate<T> one = result;
|
||||
final Predicate<T> two = f;
|
||||
result = (result == null) ? f : (signand ? new Predicate<T>() {
|
||||
result = (result == null) ? f : (and ? new Predicate<T>() {
|
||||
|
||||
@Override
|
||||
public boolean test(T t) {
|
||||
@@ -276,7 +280,7 @@ final class FilterBeanNode extends FilterNode {
|
||||
}
|
||||
});
|
||||
} else {
|
||||
putForeignPredicate(foreign, bean);
|
||||
putForeignPredicate(cache, foreign, bean);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -284,8 +288,7 @@ final class FilterBeanNode extends FilterNode {
|
||||
final String byjoinCol = this.byjoinColumn;
|
||||
final Attribute foreignAttr = this.foreignAttribute;
|
||||
for (final Map.Entry<EntityInfo, Predicate> en : foreign.entrySet()) {
|
||||
Attribute<T, Serializable> byjoinAttr = info.getAttribute(byjoinCol);
|
||||
final EntityCache cache = en.getKey().getCache();
|
||||
Attribute<T, Serializable> byjoinAttr = cache.getAttribute(byjoinCol);
|
||||
final Predicate p = en.getValue();
|
||||
Predicate<T> f = new Predicate<T>() {
|
||||
|
||||
@@ -303,7 +306,7 @@ final class FilterBeanNode extends FilterNode {
|
||||
};
|
||||
final Predicate<T> one = result;
|
||||
final Predicate<T> two = f;
|
||||
result = (result == null) ? f : (signand ? new Predicate<T>() {
|
||||
result = (result == null) ? f : (and ? new Predicate<T>() {
|
||||
|
||||
@Override
|
||||
public boolean test(T t) {
|
||||
@@ -330,21 +333,21 @@ final class FilterBeanNode extends FilterNode {
|
||||
return result;
|
||||
}
|
||||
|
||||
private <T> void putForeignPredicate(final Map<EntityInfo, Predicate> foreign, FilterBean bean) {
|
||||
private <T> void putForeignPredicate(final EntityCache<T> cache, final Map<EntityInfo, Predicate> foreign, FilterBean bean) {
|
||||
if (this.foreignEntity == null) return;
|
||||
final Serializable val = getValue(bean);
|
||||
final Serializable val = getElementValue(bean);
|
||||
Predicate filter = (val == null && express != ISNULL && express != ISNOTNULL) ? new Predicate<T>() {
|
||||
|
||||
@Override
|
||||
public boolean test(T t) {
|
||||
return signand;
|
||||
return and;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "" + signand;
|
||||
return "" + and;
|
||||
}
|
||||
} : super.createFilterPredicate(this.columnAttribute, val);
|
||||
} : super.createElementPredicate(cache, this.columnAttribute, bean);
|
||||
if (filter == null) return;
|
||||
Predicate p = foreign.get(this.foreignEntity);
|
||||
if (p == null) {
|
||||
@@ -352,7 +355,7 @@ final class FilterBeanNode extends FilterNode {
|
||||
} else {
|
||||
final Predicate<T> one = p;
|
||||
final Predicate<T> two = filter;
|
||||
p = signand ? new Predicate<T>() {
|
||||
p = and ? new Predicate<T>() {
|
||||
|
||||
@Override
|
||||
public boolean test(T t) {
|
||||
@@ -380,12 +383,12 @@ final class FilterBeanNode extends FilterNode {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isJoinAllCached() {
|
||||
protected boolean isCacheUseable() {
|
||||
return joinallcached;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Serializable getValue(FilterBean bean) {
|
||||
protected Serializable getElementValue(FilterBean bean) {
|
||||
if (bean == null || beanAttribute == null) return null;
|
||||
Serializable rs = (Serializable) beanAttribute.get(bean);
|
||||
if (rs == null) return null;
|
||||
|
||||
66
src/com/wentch/redkale/source/FilterJoinNode.java
Normal file
66
src/com/wentch/redkale/source/FilterJoinNode.java
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package com.wentch.redkale.source;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public final class FilterJoinNode extends FilterNode {
|
||||
|
||||
private Class joinClass;
|
||||
|
||||
private String joinColumn;
|
||||
|
||||
private String foreignColumn;
|
||||
|
||||
public FilterJoinNode() {
|
||||
}
|
||||
|
||||
protected FilterJoinNode(Class joinClass, String joinColumn, String foreignColumn) {
|
||||
this.joinClass = joinClass;
|
||||
this.joinColumn = joinColumn;
|
||||
this.foreignColumn = foreignColumn;
|
||||
}
|
||||
|
||||
public static FilterJoinNode create(Class joinClass, String joinColumn) {
|
||||
return create(joinClass, joinColumn, joinColumn);
|
||||
}
|
||||
|
||||
public static FilterJoinNode create(Class joinClass, String joinColumn, String foreignColumn) {
|
||||
Objects.requireNonNull(joinClass);
|
||||
Objects.requireNonNull(joinColumn);
|
||||
Objects.requireNonNull(foreignColumn);
|
||||
return new FilterJoinNode(joinClass, joinColumn, foreignColumn);
|
||||
}
|
||||
|
||||
public Class getJoinClass() {
|
||||
return joinClass;
|
||||
}
|
||||
|
||||
public void setJoinClass(Class joinClass) {
|
||||
this.joinClass = joinClass;
|
||||
}
|
||||
|
||||
public String getJoinColumn() {
|
||||
return joinColumn;
|
||||
}
|
||||
|
||||
public void setJoinColumn(String joinColumn) {
|
||||
this.joinColumn = joinColumn;
|
||||
}
|
||||
|
||||
public String getForeignColumn() {
|
||||
return foreignColumn;
|
||||
}
|
||||
|
||||
public void setForeignColumn(String foreignColumn) {
|
||||
this.foreignColumn = foreignColumn;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -38,12 +38,11 @@ public class FilterNode {
|
||||
protected Serializable value;
|
||||
|
||||
//----------------------------------------------
|
||||
|
||||
protected boolean signand = true;
|
||||
protected boolean and = true;
|
||||
|
||||
protected FilterNode[] nodes;
|
||||
|
||||
protected FilterNode() {
|
||||
public FilterNode() {
|
||||
}
|
||||
|
||||
protected FilterNode(String col, FilterExpress exp, Serializable val) {
|
||||
@@ -69,7 +68,7 @@ public class FilterNode {
|
||||
}
|
||||
|
||||
public final FilterNode and(String column, Serializable value) {
|
||||
return and(new FilterNode(column, null, value));
|
||||
return and(column, null, value);
|
||||
}
|
||||
|
||||
public final FilterNode and(String column, FilterExpress express, Serializable value) {
|
||||
@@ -81,7 +80,7 @@ public class FilterNode {
|
||||
}
|
||||
|
||||
public final FilterNode or(String column, Serializable value) {
|
||||
return or(new FilterNode(column, null, value));
|
||||
return or(column, null, value);
|
||||
}
|
||||
|
||||
public final FilterNode or(String column, FilterExpress express, Serializable value) {
|
||||
@@ -90,12 +89,18 @@ public class FilterNode {
|
||||
|
||||
protected final FilterNode any(FilterNode node, boolean sign) {
|
||||
Objects.requireNonNull(node);
|
||||
if (nodes == null) {
|
||||
nodes = new FilterNode[]{node};
|
||||
this.signand = sign;
|
||||
if (this.column == null) {
|
||||
this.column = node.column;
|
||||
this.express = node.express;
|
||||
this.value = node.value;
|
||||
return this;
|
||||
}
|
||||
if (signand == sign) {
|
||||
if (nodes == null) {
|
||||
nodes = new FilterNode[]{node};
|
||||
this.and = sign;
|
||||
return this;
|
||||
}
|
||||
if (and == sign) {
|
||||
FilterNode[] newsiblings = new FilterNode[nodes.length + 1];
|
||||
System.arraycopy(nodes, 0, newsiblings, 0, nodes.length);
|
||||
newsiblings[nodes.length] = node;
|
||||
@@ -106,23 +111,51 @@ public class FilterNode {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 该方法需要重载
|
||||
*
|
||||
* @param node
|
||||
* @param sign
|
||||
*/
|
||||
protected void append(FilterNode node, boolean sign) {
|
||||
FilterNode newnode = new FilterNode(this.column, this.express, this.value);
|
||||
newnode.signand = this.signand;
|
||||
newnode.and = this.and;
|
||||
newnode.nodes = this.nodes;
|
||||
this.nodes = new FilterNode[]{newnode, node};
|
||||
this.tabalis = null;
|
||||
this.column = null;
|
||||
this.express = null;
|
||||
this.signand = sign;
|
||||
this.and = sign;
|
||||
this.value = null;
|
||||
}
|
||||
|
||||
protected Serializable getValue(FilterBean bean) {
|
||||
/**
|
||||
* 该方法需要重载
|
||||
*
|
||||
* @param bean
|
||||
* @return
|
||||
*/
|
||||
protected Serializable getElementValue(final FilterBean bean) {
|
||||
return value;
|
||||
}
|
||||
|
||||
protected boolean isJoinAllCached() {
|
||||
/**
|
||||
* 该方法需要重载
|
||||
*
|
||||
* @param <T>
|
||||
* @param info
|
||||
* @return
|
||||
*/
|
||||
protected <T> CharSequence createSQLJoin(final EntityInfo<T> info) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 该方法需要重载
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected boolean isCacheUseable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -134,50 +167,42 @@ public class FilterNode {
|
||||
return new FilterNode(column, express, value);
|
||||
}
|
||||
|
||||
protected final <T> StringBuilder createFilterSQLExpress(final EntityInfo<T> info, FilterBean bean) {
|
||||
return createFilterSQLExpress(true, info, bean);
|
||||
}
|
||||
|
||||
protected <T> StringBuilder createFilterSQLExpress(final boolean first, final EntityInfo<T> info, FilterBean bean) {
|
||||
final Serializable val = getValue(bean);
|
||||
if (val == null && (express == ISNULL || express == ISNOTNULL)) return new StringBuilder(0);
|
||||
StringBuilder sb0 = createFilterSQLExpress(info, val);
|
||||
if (this.nodes == null) {
|
||||
if (sb0 == null) return new StringBuilder(0);
|
||||
if (!first) return sb0;
|
||||
return new StringBuilder(sb0.length() + 8).append(" WHERE ").append(sb0);
|
||||
}
|
||||
protected final <T> CharSequence createSQLExpress(final EntityInfo<T> info, final FilterBean bean) {
|
||||
CharSequence sb0 = createElementSQLExpress(info, bean);
|
||||
if (this.nodes == null) return sb0;
|
||||
final StringBuilder rs = new StringBuilder();
|
||||
rs.append(first ? " WHERE (" : " (");
|
||||
rs.append('(');
|
||||
boolean more = false;
|
||||
if (sb0 != null && sb0.length() > 2) {
|
||||
more = true;
|
||||
rs.append(sb0);
|
||||
}
|
||||
for (FilterNode node : this.nodes) {
|
||||
StringBuilder f = node.createFilterSQLExpress(false, info, bean);
|
||||
CharSequence f = node.createSQLExpress(info, bean);
|
||||
if (f == null || f.length() < 3) continue;
|
||||
if (more) rs.append(signand ? " AND " : " OR ");
|
||||
if (more) rs.append(and ? " AND " : " OR ");
|
||||
rs.append(f);
|
||||
more = true;
|
||||
}
|
||||
rs.append(')');
|
||||
if (rs.length() < (first ? 10 : 5)) return new StringBuilder(0);
|
||||
if (rs.length() < 5) return null;
|
||||
return rs;
|
||||
}
|
||||
|
||||
private <T> StringBuilder createFilterSQLExpress(final EntityInfo<T> info, Serializable val0) {
|
||||
protected final <T> CharSequence createElementSQLExpress(final EntityInfo<T> info, final FilterBean bean) {
|
||||
if (column == null) return null;
|
||||
final StringBuilder val = formatValue(val0);
|
||||
if (express == ISNULL || express == ISNOTNULL) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (tabalis != null) sb.append(tabalis).append('.');
|
||||
sb.append(info.getSQLColumn(column)).append(' ').append(express.value());
|
||||
return sb;
|
||||
}
|
||||
final StringBuilder val = formatToString(express, getElementValue(bean));
|
||||
if (val == null) return null;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
StringBuilder sb = new StringBuilder(32);
|
||||
if (tabalis != null) sb.append(tabalis).append('.');
|
||||
sb.append(info.getSQLColumn(column)).append(' ');
|
||||
switch (express) {
|
||||
case ISNULL:
|
||||
case ISNOTNULL:
|
||||
sb.append(express.value());
|
||||
break;
|
||||
case OPAND:
|
||||
case OPOR:
|
||||
sb.append(express.value()).append(' ').append(val).append(" > 0");
|
||||
@@ -192,45 +217,16 @@ public class FilterNode {
|
||||
return sb;
|
||||
}
|
||||
|
||||
protected static <E> String createFilterSQLOrderBy(EntityInfo<E> info, Flipper flipper) {
|
||||
if (flipper == null || flipper.getSort() == null || flipper.getSort().isEmpty()) return "";
|
||||
final String sort = flipper.getSort();
|
||||
String sql = info.getSortOrderbySql(sort);
|
||||
if (sql != null) return sql;
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append(" ORDER BY ");
|
||||
if (info.isNoAlias()) {
|
||||
sb.append(sort);
|
||||
} else {
|
||||
boolean flag = false;
|
||||
for (String item : sort.split(",")) {
|
||||
if (item.isEmpty()) continue;
|
||||
String[] sub = item.split("\\s+");
|
||||
if (flag) sb.append(',');
|
||||
if (sub.length < 2 || sub[1].equalsIgnoreCase("ASC")) {
|
||||
sb.append("a.").append(info.getSQLColumn(sub[0])).append(" ASC");
|
||||
} else {
|
||||
sb.append("a.").append(info.getSQLColumn(sub[0])).append(" DESC");
|
||||
}
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
sql = sb.toString();
|
||||
info.putSortOrderbySql(sort, sql);
|
||||
return sql;
|
||||
}
|
||||
|
||||
protected <T> Predicate<T> createFilterPredicate(final EntityInfo<T> info, FilterBean bean) {
|
||||
if (info == null || (column == null && this.nodes == null)) return null;
|
||||
final Serializable val = getValue(bean);
|
||||
Predicate<T> filter = createFilterPredicate(column == null ? null : info.getAttribute(column), val);
|
||||
protected <T> Predicate<T> createPredicate(final EntityCache<T> cache, final FilterBean bean) {
|
||||
if (cache == null || (column == null && this.nodes == null)) return null;
|
||||
Predicate<T> filter = createElementPredicate(cache, bean);
|
||||
if (this.nodes == null) return filter;
|
||||
for (FilterNode node : this.nodes) {
|
||||
Predicate<T> f = node.createFilterPredicate(info, bean);
|
||||
Predicate<T> f = node.createPredicate(cache, bean);
|
||||
if (f == null) continue;
|
||||
final Predicate<T> one = filter;
|
||||
final Predicate<T> two = f;
|
||||
filter = (filter == null) ? f : (signand ? new Predicate<T>() {
|
||||
filter = (filter == null) ? f : (and ? new Predicate<T>() {
|
||||
|
||||
@Override
|
||||
public boolean test(T t) {
|
||||
@@ -257,35 +253,39 @@ public class FilterNode {
|
||||
return filter;
|
||||
}
|
||||
|
||||
protected final <T> Predicate<T> createFilterPredicate(final Attribute<T, Serializable> attr, Serializable val0) {
|
||||
if (val0 == null) {
|
||||
if (express == ISNULL) return new Predicate<T>() {
|
||||
protected final <T> Predicate<T> createElementPredicate(final EntityCache<T> cache, final FilterBean bean) {
|
||||
return createElementPredicate(cache, cache.getAttribute(column), bean);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(T t) {
|
||||
return attr.get(t) == null;
|
||||
}
|
||||
protected final <T> Predicate<T> createElementPredicate(final EntityCache<T> cache, final Attribute<T, Serializable> attr, final FilterBean bean) {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return attr.field() + " = null";
|
||||
}
|
||||
};
|
||||
if (express == ISNOTNULL) return new Predicate<T>() {
|
||||
if (express == ISNULL) return new Predicate<T>() {
|
||||
|
||||
@Override
|
||||
public boolean test(T t) {
|
||||
return attr.get(t) != null;
|
||||
}
|
||||
@Override
|
||||
public boolean test(T t) {
|
||||
return attr.get(t) == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return attr.field() + " != null";
|
||||
}
|
||||
};
|
||||
return null;
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return attr.field() + " = null";
|
||||
}
|
||||
};
|
||||
if (express == ISNOTNULL) return new Predicate<T>() {
|
||||
|
||||
@Override
|
||||
public boolean test(T t) {
|
||||
return attr.get(t) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return attr.field() + " != null";
|
||||
}
|
||||
};
|
||||
if (attr == null) return null;
|
||||
Serializable val0 = getElementValue(bean);
|
||||
if (val0 == null) return null;
|
||||
|
||||
final Class atype = attr.type();
|
||||
final Class valtype = val0.getClass();
|
||||
@@ -743,174 +743,51 @@ public class FilterNode {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected static <E> Comparator<E> createFilterComparator(EntityCache<E> cache, Flipper flipper) {
|
||||
if (flipper == null || flipper.getSort() == null || flipper.getSort().isEmpty()) return null;
|
||||
final String sort = flipper.getSort();
|
||||
Comparator<E> comparator = cache.getSortComparator(sort);
|
||||
if (comparator != null) return comparator;
|
||||
for (String item : sort.split(",")) {
|
||||
if (item.trim().isEmpty()) continue;
|
||||
String[] sub = item.trim().split("\\s+");
|
||||
int pos = sub[0].indexOf('(');
|
||||
Attribute<E, Serializable> attr;
|
||||
if (pos <= 0) {
|
||||
attr = cache.info.getAttribute(sub[0]);
|
||||
} else { //含SQL函数
|
||||
int pos2 = sub[0].lastIndexOf(')');
|
||||
final Attribute<E, Serializable> pattr = cache.info.getAttribute(sub[0].substring(pos + 1, pos2));
|
||||
final String func = sub[0].substring(0, pos);
|
||||
if ("ABS".equalsIgnoreCase(func)) {
|
||||
if (pattr.type() == int.class || pattr.type() == Integer.class) {
|
||||
attr = new Attribute<E, Serializable>() {
|
||||
|
||||
@Override
|
||||
public Class type() {
|
||||
return pattr.type();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class declaringClass() {
|
||||
return pattr.declaringClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String field() {
|
||||
return pattr.field();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Serializable get(E obj) {
|
||||
return Math.abs(((Number) pattr.get(obj)).intValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(E obj, Serializable value) {
|
||||
pattr.set(obj, value);
|
||||
}
|
||||
};
|
||||
} else if (pattr.type() == long.class || pattr.type() == Long.class) {
|
||||
attr = new Attribute<E, Serializable>() {
|
||||
|
||||
@Override
|
||||
public Class type() {
|
||||
return pattr.type();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class declaringClass() {
|
||||
return pattr.declaringClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String field() {
|
||||
return pattr.field();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Serializable get(E obj) {
|
||||
return Math.abs(((Number) pattr.get(obj)).longValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(E obj, Serializable value) {
|
||||
pattr.set(obj, value);
|
||||
}
|
||||
};
|
||||
} else if (pattr.type() == float.class || pattr.type() == Float.class) {
|
||||
attr = new Attribute<E, Serializable>() {
|
||||
|
||||
@Override
|
||||
public Class type() {
|
||||
return pattr.type();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class declaringClass() {
|
||||
return pattr.declaringClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String field() {
|
||||
return pattr.field();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Serializable get(E obj) {
|
||||
return Math.abs(((Number) pattr.get(obj)).floatValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(E obj, Serializable value) {
|
||||
pattr.set(obj, value);
|
||||
}
|
||||
};
|
||||
} else if (pattr.type() == double.class || pattr.type() == Double.class) {
|
||||
attr = new Attribute<E, Serializable>() {
|
||||
|
||||
@Override
|
||||
public Class type() {
|
||||
return pattr.type();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class declaringClass() {
|
||||
return pattr.declaringClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String field() {
|
||||
return pattr.field();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Serializable get(E obj) {
|
||||
return Math.abs(((Number) pattr.get(obj)).doubleValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(E obj, Serializable value) {
|
||||
pattr.set(obj, value);
|
||||
}
|
||||
};
|
||||
} else {
|
||||
throw new RuntimeException("Flipper not supported sort illegal type by ABS (" + flipper.getSort() + ")");
|
||||
}
|
||||
} else if (func.isEmpty()) {
|
||||
attr = pattr;
|
||||
} else {
|
||||
throw new RuntimeException("Flipper not supported sort illegal function (" + flipper.getSort() + ")");
|
||||
}
|
||||
}
|
||||
Comparator<E> c = (sub.length > 1 && sub[1].equalsIgnoreCase("DESC")) ? (E o1, E o2) -> {
|
||||
Comparable c1 = (Comparable) attr.get(o1);
|
||||
Comparable c2 = (Comparable) attr.get(o2);
|
||||
return c2 == null ? -1 : c2.compareTo(c1);
|
||||
} : (E o1, E o2) -> {
|
||||
Comparable c1 = (Comparable) attr.get(o1);
|
||||
Comparable c2 = (Comparable) attr.get(o2);
|
||||
return c1 == null ? -1 : c1.compareTo(c2);
|
||||
};
|
||||
|
||||
if (comparator == null) {
|
||||
comparator = c;
|
||||
} else {
|
||||
comparator = comparator.thenComparing(c);
|
||||
}
|
||||
}
|
||||
cache.putSortComparator(sort, comparator);
|
||||
return comparator;
|
||||
@Override
|
||||
public String toString() {
|
||||
return toString(null);
|
||||
}
|
||||
|
||||
protected StringBuilder formatValue(Object value) {
|
||||
return formatValue(express, value);
|
||||
public String toString(final FilterBean bean) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (nodes == null) {
|
||||
if (column != null) {
|
||||
Serializable ev = getElementValue(bean);
|
||||
if (express == ISNULL || express == ISNOTNULL) {
|
||||
sb.append(column).append(' ').append(express.value());
|
||||
} else if (ev != null) {
|
||||
sb.append(column).append(' ').append(express.value()).append(' ').append(formatToString(express, ev));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
boolean more = false;
|
||||
if (column != null) {
|
||||
Serializable ev = getElementValue(bean);
|
||||
if (express == ISNULL || express == ISNOTNULL) {
|
||||
sb.append('(').append(column).append(' ').append(express.value());
|
||||
more = true;
|
||||
} else if (ev != null) {
|
||||
sb.append('(').append(column).append(' ').append(express.value()).append(' ').append(formatToString(express, ev));
|
||||
more = true;
|
||||
}
|
||||
}
|
||||
for (FilterNode node : this.nodes) {
|
||||
String s = node.toString();
|
||||
if (s.isEmpty()) continue;
|
||||
if (sb.length() > 0) sb.append(and ? " AND " : " OR ");
|
||||
sb.append(s);
|
||||
}
|
||||
if (more) sb.append(')');
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
protected static String formatToString(Object value) {
|
||||
StringBuilder sb = formatValue(null, value);
|
||||
StringBuilder sb = formatToString(null, value);
|
||||
return sb == null ? null : sb.toString();
|
||||
}
|
||||
|
||||
private static StringBuilder formatValue(FilterExpress express, Object value) {
|
||||
private static StringBuilder formatToString(FilterExpress express, Object value) {
|
||||
if (value == null) return null;
|
||||
if (value instanceof Number) return new StringBuilder().append(value);
|
||||
if (value instanceof CharSequence) {
|
||||
@@ -937,7 +814,7 @@ public class FilterNode {
|
||||
if (len == 0) return express == NOTIN ? null : new StringBuilder("(NULL)");
|
||||
if (len == 1) {
|
||||
Object firstval = Array.get(value, 0);
|
||||
if (firstval != null && firstval.getClass().isArray()) return formatValue(express, firstval);
|
||||
if (firstval != null && firstval.getClass().isArray()) return formatToString(express, firstval);
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append('(');
|
||||
@@ -969,67 +846,51 @@ public class FilterNode {
|
||||
return new StringBuilder().append(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (nodes == null) {
|
||||
sb.append(column).append(' ').append(express.value()).append(' ').append(formatValue(value));
|
||||
} else {
|
||||
if (column != null) sb.append('(').append(column).append(' ').append(express.value()).append(' ').append(formatValue(value));
|
||||
for (FilterNode node : this.nodes) {
|
||||
if (sb.length() > 0) sb.append(signand ? " AND " : " OR ");
|
||||
sb.append(node.toString());
|
||||
}
|
||||
sb.append(')');
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public Serializable getValue() {
|
||||
public final Serializable getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(Serializable value) {
|
||||
public final void setValue(Serializable value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public boolean isSignand() {
|
||||
return signand;
|
||||
public final boolean isAnd() {
|
||||
return and;
|
||||
}
|
||||
|
||||
public void setSignand(boolean signand) {
|
||||
this.signand = signand;
|
||||
public final void setAnd(boolean and) {
|
||||
this.and = and;
|
||||
}
|
||||
|
||||
public String getTabalis() {
|
||||
public final String getTabalis() {
|
||||
return tabalis;
|
||||
}
|
||||
|
||||
public void setTabalis(String tabalis) {
|
||||
public final void setTabalis(String tabalis) {
|
||||
this.tabalis = tabalis;
|
||||
}
|
||||
|
||||
public String getColumn() {
|
||||
public final String getColumn() {
|
||||
return column;
|
||||
}
|
||||
|
||||
public void setColumn(String column) {
|
||||
public final void setColumn(String column) {
|
||||
this.column = column;
|
||||
}
|
||||
|
||||
public FilterExpress getExpress() {
|
||||
public final FilterExpress getExpress() {
|
||||
return express;
|
||||
}
|
||||
|
||||
public void setExpress(FilterExpress express) {
|
||||
public final void setExpress(FilterExpress express) {
|
||||
this.express = express;
|
||||
}
|
||||
|
||||
public FilterNode[] getNodes() {
|
||||
public final FilterNode[] getNodes() {
|
||||
return nodes;
|
||||
}
|
||||
|
||||
public void setNodes(FilterNode[] nodes) {
|
||||
public final void setNodes(FilterNode[] nodes) {
|
||||
this.nodes = nodes;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user