改版EntityXInfo
This commit is contained in:
@@ -1749,7 +1749,7 @@ public final class DataJDBCSource implements DataSource {
|
||||
if (valid) filter = finfo.getFilterPredicate(info, bean);
|
||||
}
|
||||
if (valid) {
|
||||
Sheet<T> sheet = cache.querySheet(selects, filter, flipper, FilterNode.getSortComparator(info, flipper));
|
||||
Sheet<T> sheet = cache.querySheet(selects, filter, flipper, FilterNode.createFilterComparator(info, flipper));
|
||||
if (!sheet.isEmpty() || cache.isFullLoaded()) return sheet;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,7 +209,7 @@ public final class EntityInfo<T> {
|
||||
this.allocationSize = allocationSize0;
|
||||
//----------------cache--------------
|
||||
Cacheable c = type.getAnnotation(Cacheable.class);
|
||||
boolean cf = (c == null) ? (cacheClasses != null && cacheClasses.contains(type)) : false;
|
||||
boolean cf = (c == null && cacheClasses != null && cacheClasses.contains(type));
|
||||
if ((c != null && c.value()) || cf) {
|
||||
this.cache = new EntityCache<>(type, creator, primary, attributes, fullloader);
|
||||
} else {
|
||||
|
||||
@@ -6,19 +6,141 @@
|
||||
package com.wentch.redkale.source;
|
||||
|
||||
import static com.wentch.redkale.source.FilterExpress.*;
|
||||
import com.wentch.redkale.util.Attribute;
|
||||
import com.wentch.redkale.util.*;
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.*;
|
||||
import java.util.Collection;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Function;
|
||||
import java.util.logging.Logger;
|
||||
import javax.persistence.Transient;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public class FilterBeanNode extends FilterNode {
|
||||
@SuppressWarnings("unchecked")
|
||||
final class FilterBeanNode extends FilterNode {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(FilterBeanNode.class.getSimpleName());
|
||||
|
||||
private static final ConcurrentHashMap<Class, FilterBeanNode> beanodes = new ConcurrentHashMap<>();
|
||||
|
||||
public static <T extends FilterBean> FilterBeanNode load(Class<T> clazz, final int nodeid,
|
||||
Function<Class, List> fullloader) {
|
||||
FilterBeanNode rs = beanodes.get(clazz);
|
||||
if (rs != null) return rs;
|
||||
synchronized (beanodes) {
|
||||
rs = beanodes.get(clazz);
|
||||
if (rs == null) {
|
||||
rs = createNode(clazz, nodeid, fullloader);
|
||||
beanodes.put(clazz, rs);
|
||||
}
|
||||
return rs;
|
||||
}
|
||||
}
|
||||
|
||||
private static <T extends FilterBean> FilterBeanNode createNode(Class<T> clazz, final int nodeid,
|
||||
Function<Class, List> fullloader) {
|
||||
Class cltmp = clazz;
|
||||
Set<String> fields = new HashSet<>();
|
||||
final Map<Class, String> joinTables = new HashMap<>();
|
||||
Map<String, FilterBeanNode> nodemap = new HashMap<>();
|
||||
boolean joinallcached = true;
|
||||
final StringBuilder joinsb = new StringBuilder();
|
||||
do {
|
||||
for (Field field : cltmp.getDeclaredFields()) {
|
||||
if (Modifier.isStatic(field.getModifiers())) continue;
|
||||
if (fields.contains(field.getName())) continue;
|
||||
if (field.getAnnotation(Ignore.class) != null) continue;
|
||||
if (field.getAnnotation(Transient.class) != null) continue;
|
||||
|
||||
char[] chars = field.getName().toCharArray();
|
||||
chars[0] = Character.toUpperCase(chars[0]);
|
||||
final Class t = field.getType();
|
||||
Method getter = null;
|
||||
try {
|
||||
getter = cltmp.getMethod(((t == boolean.class || t == Boolean.class) ? "is" : "get") + new String(chars));
|
||||
} catch (Exception ex) {
|
||||
continue;
|
||||
}
|
||||
fields.add(field.getName());
|
||||
FilterBeanNode newnode = new FilterBeanNode(field.getName(), true, Attribute.create(getter, null));
|
||||
newnode.setField(field);
|
||||
//------------------------------------
|
||||
{
|
||||
FilterJoinColumn joinCol = field.getAnnotation(FilterJoinColumn.class);
|
||||
if (joinCol != null) {
|
||||
boolean first = false;
|
||||
final Class joinClass = joinCol.table();
|
||||
if (!joinTables.containsKey(joinClass)) {
|
||||
first = true;
|
||||
joinTables.put(joinClass, String.valueOf((char) ('b' + joinTables.size())));
|
||||
}
|
||||
final String alias = joinTables.get(joinClass);
|
||||
final EntityInfo secinfo = EntityInfo.load(joinClass, nodeid, fullloader);
|
||||
if (secinfo.getCache() == null || !secinfo.getCache().isFullLoaded()) {
|
||||
joinallcached = false;
|
||||
}
|
||||
if (first) {
|
||||
joinsb.append(" ").append(joinCol.type().name()).append(" JOIN ").append(secinfo.getTable())
|
||||
.append(" ").append(alias).append(" ON a.# = ").append(alias).append(".")
|
||||
.append(joinCol.column().isEmpty() ? secinfo.getPrimarySQLColumn() : secinfo.getSQLColumn(joinCol.column()));
|
||||
}
|
||||
newnode.foreignEntity = secinfo;
|
||||
newnode.tabalis = alias;
|
||||
newnode.foreignColumn = joinCol.column().isEmpty() ? secinfo.getPrimary().field() : joinCol.column();
|
||||
}
|
||||
}
|
||||
//------------------------------------
|
||||
{
|
||||
FilterGroup[] refs = field.getAnnotationsByType(FilterGroup.class);
|
||||
String[] groups = new String[refs.length];
|
||||
for (int i = 0; i < refs.length; i++) {
|
||||
groups[i] = refs[i].value();
|
||||
}
|
||||
if (groups.length == 0) groups = new String[]{"[AND]"};
|
||||
for (String key : groups) {
|
||||
if (!key.startsWith("[AND]") && !key.startsWith("[OR]")) {
|
||||
throw new RuntimeException(field + "'s FilterGroup.value(" + key + ") illegal, must be [AND] or [OR] startsWith");
|
||||
}
|
||||
FilterBeanNode node = nodemap.get(key);
|
||||
if (node == null) {
|
||||
nodemap.put(key, newnode);
|
||||
} else {
|
||||
node.any(node, !key.contains("[OR]"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} while ((cltmp = cltmp.getSuperclass()) != Object.class);
|
||||
FilterBeanNode rs = null;
|
||||
for (FilterBeanNode f : nodemap.values()) {
|
||||
if (rs == null) {
|
||||
rs = f;
|
||||
} else {
|
||||
rs.and(f);
|
||||
}
|
||||
}
|
||||
if (rs != null) {
|
||||
rs.joinallcached = joinallcached;
|
||||
if (joinsb.length() > 0) rs.joinSQL = joinsb.toString();
|
||||
}
|
||||
return rs;
|
||||
}
|
||||
|
||||
//--------------------------- only header -----------------------------------------------------
|
||||
private boolean joinallcached = true;
|
||||
|
||||
private String joinSQL;
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
private Attribute beanAttribute;
|
||||
|
||||
private EntityInfo foreignEntity;
|
||||
|
||||
private String foreignColumn;
|
||||
|
||||
private boolean array;
|
||||
|
||||
private boolean collection;
|
||||
@@ -39,7 +161,7 @@ public class FilterBeanNode extends FilterNode {
|
||||
this.beanAttribute = beanAttr;
|
||||
}
|
||||
|
||||
void setField(Field field) {
|
||||
private void setField(Field field) {
|
||||
final FilterColumn fc = field.getAnnotation(FilterColumn.class);
|
||||
if (fc != null && !fc.name().isEmpty()) this.column = fc.name();
|
||||
final Class type = field.getType();
|
||||
@@ -63,6 +185,7 @@ public class FilterBeanNode extends FilterNode {
|
||||
}
|
||||
if (exp == null) exp = EQUAL;
|
||||
this.express = exp;
|
||||
this.tabalis = "a";
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -70,6 +193,8 @@ public class FilterBeanNode extends FilterNode {
|
||||
FilterBeanNode newnode = new FilterBeanNode(this.column, this.signand, this.beanAttribute);
|
||||
newnode.express = this.express;
|
||||
newnode.nodes = this.nodes;
|
||||
newnode.foreignEntity = this.foreignEntity;
|
||||
newnode.foreignColumn = this.foreignColumn;
|
||||
newnode.array = this.array;
|
||||
newnode.collection = this.collection;
|
||||
newnode.ignoreCase = this.ignoreCase;
|
||||
@@ -85,6 +210,8 @@ public class FilterBeanNode extends FilterNode {
|
||||
if (node instanceof FilterBeanNode) {
|
||||
FilterBeanNode beanNode = ((FilterBeanNode) node);
|
||||
this.beanAttribute = beanNode.beanAttribute;
|
||||
this.foreignEntity = beanNode.foreignEntity;
|
||||
this.foreignColumn = beanNode.foreignColumn;
|
||||
this.array = beanNode.array;
|
||||
this.collection = beanNode.collection;
|
||||
this.ignoreCase = beanNode.ignoreCase;
|
||||
@@ -95,6 +222,19 @@ public class FilterBeanNode extends FilterNode {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T> StringBuilder createFilterSQLExpress(final EntityInfo<T> info, FilterBean bean) {
|
||||
if (joinSQL == null) return super.createFilterSQLExpress(info, bean);
|
||||
StringBuilder sb = super.createFilterSQLExpress(info, bean);
|
||||
String jsql = joinSQL.replace("#", info.getPrimarySQLColumn());
|
||||
return new StringBuilder(sb.length() + jsql.length()).append(jsql).append(sb);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isJoinAllCached() {
|
||||
return false && joinallcached; //暂时没实现
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Serializable getValue(FilterBean bean) {
|
||||
if (bean == null || beanAttribute == null) return null;
|
||||
|
||||
@@ -20,6 +20,8 @@ public class FilterNode {
|
||||
|
||||
protected boolean signand = true;
|
||||
|
||||
protected String tabalis;
|
||||
|
||||
protected String column;
|
||||
|
||||
protected FilterExpress express;
|
||||
@@ -96,6 +98,7 @@ public class FilterNode {
|
||||
newnode.signand = this.signand;
|
||||
newnode.nodes = this.nodes;
|
||||
this.nodes = new FilterNode[]{newnode};
|
||||
this.tabalis = node.tabalis;
|
||||
this.column = node.column;
|
||||
this.express = node.express;
|
||||
this.signand = sign;
|
||||
@@ -106,6 +109,10 @@ public class FilterNode {
|
||||
return value;
|
||||
}
|
||||
|
||||
protected boolean isJoinAllCached() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static FilterNode create(String column, Serializable value) {
|
||||
return create(column, FilterExpress.EQUAL, value);
|
||||
}
|
||||
@@ -114,13 +121,16 @@ public class FilterNode {
|
||||
return new FilterNode(column, express, value);
|
||||
}
|
||||
|
||||
protected final <T> StringBuilder createFilterSQLExpress(final EntityInfo<T> info, FilterBean bean) {
|
||||
protected <T> StringBuilder createFilterSQLExpress(final EntityInfo<T> info, FilterBean bean) {
|
||||
final Serializable val = getValue(bean);
|
||||
if (val == null && express != ISNULL && express != ISNOTNULL) return null;
|
||||
if (val == null && express != ISNULL && express != ISNOTNULL) return new StringBuilder(0);
|
||||
StringBuilder sb0 = createFilterSQLExpress(info, val);
|
||||
if (nodes == null) return sb0;
|
||||
if (nodes == null) {
|
||||
if (sb0 == null) return new StringBuilder(0);
|
||||
return new StringBuilder(sb0.length() + 8).append(" WHERE ").append(sb0);
|
||||
}
|
||||
final StringBuilder rs = new StringBuilder();
|
||||
rs.append('(');
|
||||
rs.append(" WHERE (");
|
||||
if (sb0 != null) rs.append(sb0);
|
||||
for (FilterNode node : this.nodes) {
|
||||
StringBuilder f = node.createFilterSQLExpress(info, bean);
|
||||
@@ -129,7 +139,7 @@ public class FilterNode {
|
||||
rs.append(f);
|
||||
}
|
||||
rs.append(')');
|
||||
if (rs.length() < 3) return null;
|
||||
if (rs.length() < 10) return new StringBuilder(0);
|
||||
return rs;
|
||||
}
|
||||
|
||||
@@ -137,6 +147,7 @@ public class FilterNode {
|
||||
final StringBuilder val = formatValue(val0);
|
||||
if (val == null) return null;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (tabalis != null) sb.append(tabalis).append('.');
|
||||
sb.append(info.getSQLColumn(column)).append(' ');
|
||||
switch (express) {
|
||||
case ISNULL:
|
||||
@@ -261,7 +272,30 @@ public class FilterNode {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected static <E> Comparator<E> getSortComparator(EntityInfo<E> info, Flipper flipper) {
|
||||
protected static <E> StringBuilder createFilterSQLOrderBy(EntityInfo<E> info, Flipper flipper) {
|
||||
if (flipper == null || flipper.getSort() == null || flipper.getSort().isEmpty()) return null;
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append(" ORDER BY ");
|
||||
if (info.isNoAlias()) {
|
||||
sb.append(flipper.getSort());
|
||||
} else {
|
||||
boolean flag = false;
|
||||
for (String item : flipper.getSort().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;
|
||||
}
|
||||
}
|
||||
return sb;
|
||||
}
|
||||
|
||||
protected static <E> Comparator<E> createFilterComparator(EntityInfo<E> info, Flipper flipper) {
|
||||
if (flipper == null || flipper.getSort() == null || flipper.getSort().isEmpty()) return null;
|
||||
Comparator<E> comparator = null;
|
||||
for (String item : flipper.getSort().split(",")) {
|
||||
@@ -371,6 +405,14 @@ public class FilterNode {
|
||||
this.signand = signand;
|
||||
}
|
||||
|
||||
public String getTabalis() {
|
||||
return tabalis;
|
||||
}
|
||||
|
||||
public void setTabalis(String tabalis) {
|
||||
this.tabalis = tabalis;
|
||||
}
|
||||
|
||||
public String getColumn() {
|
||||
return column;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user