改版EntityXInfo

This commit is contained in:
地平线
2015-05-31 11:40:07 +08:00
parent bef06801a0
commit a3a21cb783
5 changed files with 146 additions and 81 deletions

View File

@@ -399,7 +399,7 @@ public final class DataJDBCSource implements DataSource {
final Class primaryType = info.getPrimary().type();
final Attribute primary = info.getPrimary();
final boolean distributed = info.distributed;
Attribute<T, ?>[] attrs = info.insertAttributes;
Attribute<T, Serializable>[] attrs = info.insertAttributes;
String[] sqls = null;
if (distributed && !info.initedPrimaryValue && primaryType.isPrimitive()) {
synchronized (info) {
@@ -443,7 +443,7 @@ public final class DataJDBCSource implements DataSource {
for (final T value : values) {
int i = 0;
if (distributed) info.createPrimaryValue(value);
for (Attribute<T, ?> attr : attrs) {
for (Attribute<T, Serializable> attr : attrs) {
prestmt.setObject(++i, attr.get(value));
}
prestmt.addBatch();
@@ -456,7 +456,7 @@ public final class DataJDBCSource implements DataSource {
for (final T value : values) {
int i = 0;
if (distributed) info.createPrimaryValue(value);
for (Attribute<T, ?> attr : attrs) {
for (Attribute<T, Serializable> attr : attrs) {
Object a = attr.get(value);
ps[i] = formatToString(a);
prestmt.setObject(++i, a);
@@ -659,7 +659,7 @@ public final class DataJDBCSource implements DataSource {
//------------------------------------
final EntityCache<T> cache = info.getCache();
if (cache == null) return;
final Attribute<T, ?> attr = info.getAttribute(column);
final Attribute<T, Serializable> attr = info.getAttribute(column);
final Serializable[] keys2 = keys;
Serializable[] ids = cache.delete((T t) -> Arrays.binarySearch(keys2, attr.get(t)) >= 0);
if (cacheListener != null) cacheListener.delete(name, clazz, ids);
@@ -717,8 +717,8 @@ public final class DataJDBCSource implements DataSource {
//------------------------------------
final EntityCache<T> cache = info.getCache();
if (cache == null) return;
final Attribute<T, ?> attr1 = info.getAttribute(column1);
final Attribute<T, ?> attr2 = info.getAttribute(column2);
final Attribute<T, Serializable> attr1 = info.getAttribute(column1);
final Attribute<T, Serializable> attr2 = info.getAttribute(column2);
Serializable[] ids = cache.delete((T t) -> key1.equals(attr1.get(t)) && key2.equals(attr2.get(t)));
if (cacheListener != null) cacheListener.delete(name, clazz, ids);
} catch (SQLException e) {
@@ -771,12 +771,12 @@ public final class DataJDBCSource implements DataSource {
final EntityInfo<T> info = loadEntityInfo(clazz);
if (debug.get()) logger.finest(clazz.getSimpleName() + " update sql=" + info.updateSQL);
final PreparedStatement prestmt = conn.prepareStatement(info.updateSQL);
Attribute<T, ?>[] attrs = info.updateAttributes;
Attribute<T, Serializable>[] attrs = info.updateAttributes;
String[] sqls = null;
if (writeListener == null) {
for (final T value : values) {
int i = 0;
for (Attribute<T, ?> attr : attrs) {
for (Attribute<T, Serializable> attr : attrs) {
prestmt.setObject(++i, attr.get(value));
}
prestmt.addBatch();
@@ -788,7 +788,7 @@ public final class DataJDBCSource implements DataSource {
int index = 0;
for (final T value : values) {
int i = 0;
for (Attribute<T, ?> attr : attrs) {
for (Attribute<T, Serializable> attr : attrs) {
Object a = attr.get(value);
ps[i] = formatToString(a);
prestmt.setObject(++i, a);
@@ -924,7 +924,7 @@ public final class DataJDBCSource implements DataSource {
//---------------------------------------------------
final EntityCache<T> cache = info.getCache();
if (cache == null) return;
Attribute<T, Object> attr = (Attribute<T, Object>) info.getAttribute(column);
Attribute<T, Serializable> attr = info.getAttribute(column);
T value = cache.updateColumnIncrement(id, attr, incvalue);
if (value != null && cacheListener != null) cacheListener.update(name, clazz, value);
} catch (SQLException e) {
@@ -970,7 +970,7 @@ public final class DataJDBCSource implements DataSource {
final Class<T> clazz = (Class<T>) value.getClass();
final EntityInfo<T> info = loadEntityInfo(clazz);
StringBuilder setsql = new StringBuilder();
Attribute<T, ?>[] attrs = new Attribute[columns.length];
Attribute<T, Serializable>[] attrs = new Attribute[columns.length];
int i = - 1;
final Serializable id = (Serializable) info.getPrimary().get(value);
for (String col : columns) {
@@ -1206,8 +1206,8 @@ public final class DataJDBCSource implements DataSource {
final EntityInfo<T> info = loadEntityInfo(clazz);
final EntityCache<T> cache = info.getCache();
if (cache != null) {
final Attribute<T, ?> attr1 = info.getAttribute(column1);
final Attribute<T, ?> attr2 = info.getAttribute(column2);
final Attribute<T, Serializable> attr1 = info.getAttribute(column1);
final Attribute<T, Serializable> attr2 = info.getAttribute(column2);
T r = cache.find((T t) -> key1.equals(attr1.get(t)) && key2.equals(attr2.get(t)));
if (r != null || cache.isFullLoaded()) return r;
}
@@ -1278,7 +1278,7 @@ public final class DataJDBCSource implements DataSource {
final EntityInfo<T> info = loadEntityInfo(clazz);
final EntityCache<T> cache = info.getCache();
if (cache != null) {
Attribute<T, ?> idattr = info.getAttribute(column);
Attribute<T, Serializable> idattr = info.getAttribute(column);
List<T> list = cache.queryList(selects, (x) -> Arrays.binarySearch(keys, idattr.get(x)) >= 0, null);
final T[] rs = (T[]) Array.newInstance(clazz, keys.length);
if (!list.isEmpty()) {
@@ -1573,7 +1573,7 @@ public final class DataJDBCSource implements DataSource {
return sql;
}
private <T> Predicate<T> genFilter(final Attribute<T, ?> attr, FilterExpress express, Serializable key) {
private <T> Predicate<T> genFilter(final Attribute<T, Serializable> attr, FilterExpress express, Serializable key) {
Predicate<T> filter = null;
switch (express) {
case EQUAL:
@@ -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, FilterInfo.getSortComparator(info, flipper));
Sheet<T> sheet = cache.querySheet(selects, filter, flipper, FilterNode.getSortComparator(info, flipper));
if (!sheet.isEmpty() || cache.isFullLoaded()) return sheet;
}
}
@@ -2296,7 +2296,7 @@ public final class DataJDBCSource implements DataSource {
return inner.getAttribute(fieldname).field();
}
public Attribute<T, ?> getAttribute(String fieldname) {
public Attribute<T, Serializable> getAttribute(String fieldname) {
return inner.getAttribute(fieldname);
}
}

View File

@@ -36,14 +36,14 @@ final class EntityCache<T> {
private final Attribute<T, Serializable> primary;
//key是field的name
private final Map<String, Attribute<T, ?>> attributes;
private final Map<String, Attribute<T, Serializable>> attributes;
private final Reproduce<T, T> reproduce;
private boolean fullloaded;
public EntityCache(final Class<T> type, Creator<T> creator,
Attribute<T, Serializable> primary, Map<String, Attribute<T, ?>> attributes) {
Attribute<T, Serializable> primary, Map<String, Attribute<T, Serializable>> attributes) {
this.type = type;
this.creator = creator;
this.primary = primary;
@@ -63,7 +63,7 @@ final class EntityCache<T> {
public void fullLoad(List<T> all) {
clear();
all.stream().filter(x -> x != null).forEach(x -> this.map.put((Serializable) this.primary.get(x), x));
all.stream().filter(x -> x != null).forEach(x -> this.map.put(this.primary.get(x), x));
this.list.addAll(all);
this.fullloaded = true;
}
@@ -168,8 +168,8 @@ final class EntityCache<T> {
if (selects == null) {
stream.forEach(x -> rs.add(needcopy ? reproduce.copy(creator.create(), x) : x));
} else {
final List<Attribute<T, ?>> attrs = new ArrayList<>();
for (Map.Entry<String, Attribute<T, ?>> en : this.attributes.entrySet()) {
final List<Attribute<T, Serializable>> attrs = new ArrayList<>();
for (Map.Entry<String, Attribute<T, Serializable>> en : this.attributes.entrySet()) {
if (selects.validate(en.getKey())) attrs.add(en.getValue());
}
stream.forEach(x -> {
@@ -207,8 +207,8 @@ final class EntityCache<T> {
if (selects == null) {
stream.forEach(x -> rs.add(needcopy ? reproduce.copy(creator.create(), x) : x));
} else {
final List<Attribute<T, ?>> attrs = new ArrayList<>();
for (Map.Entry<String, Attribute<T, ?>> en : this.attributes.entrySet()) {
final List<Attribute<T, Serializable>> attrs = new ArrayList<>();
for (Map.Entry<String, Attribute<T, Serializable>> en : this.attributes.entrySet()) {
if (selects.validate(en.getKey())) attrs.add(en.getValue());
}
stream.forEach(x -> {
@@ -225,7 +225,7 @@ final class EntityCache<T> {
public void insert(T value) {
if (value == null) return;
T rs = reproduce.copy(this.creator.create(), value); //确保同一主键值的map与list中的对象必须共用。
T old = this.map.put((Serializable) this.primary.get(rs), rs);
T old = this.map.put(this.primary.get(rs), rs);
if (old != null) logger.log(Level.WARNING, "cache repeat insert data: " + value);
this.list.add(rs);
}
@@ -243,7 +243,7 @@ final class EntityCache<T> {
int i = -1;
for (Object o : rms) {
T t = (T) o;
ids[++i] = (Serializable) this.primary.get(t);
ids[++i] = this.primary.get(t);
this.map.remove(ids[i]);
this.list.remove(t);
}
@@ -252,14 +252,14 @@ final class EntityCache<T> {
public void update(final T value) {
if (value == null) return;
T rs = this.map.get((Serializable) this.primary.get(value));
T rs = this.map.get(this.primary.get(value));
if (rs == null) return;
this.reproduce.copy(rs, value);
}
public void update(final T value, Attribute<T, ?>[] attrs) {
public void update(final T value, Attribute<T, Serializable>[] attrs) {
if (value == null) return;
T rs = this.map.get((Serializable) this.primary.get(value));
T rs = this.map.get(this.primary.get(value));
if (rs == null) return;
for (Attribute attr : attrs) {
attr.set(rs, attr.get(value));

View File

@@ -47,19 +47,21 @@ public final class EntityInfo<T> {
//key是field的name 不是sql字段。
//存放所有与数据库对应的字段, 包括主键
private final Map<String, Attribute<T, ?>> attributes = new HashMap<>();
private final Map<String, Attribute<T, Serializable>> attributes = new HashMap<>();
private final Map<String, Attribute<T, Serializable>> updateAttributeMap = new HashMap<>();
final String querySQL;
private final Attribute<T, Object>[] queryAttributes; //数据库中所有字段
private final Attribute<T, Serializable>[] queryAttributes; //数据库中所有字段
final String insertSQL;
final Attribute<T, Object>[] insertAttributes; //数据库中所有可新增字段
final Attribute<T, Serializable>[] insertAttributes; //数据库中所有可新增字段
final String updateSQL;
final Attribute<T, Object>[] updateAttributes; //数据库中所有可更新字段
final Attribute<T, Serializable>[] updateAttributes; //数据库中所有可更新字段
final String deleteSQL;
@@ -120,11 +122,11 @@ public final class EntityInfo<T> {
Map<String, String> aliasmap0 = null;
Class cltmp = type;
Set<String> fields = new HashSet<>();
List<Attribute<T, ?>> queryattrs = new ArrayList<>();
List<Attribute<T, Serializable>> queryattrs = new ArrayList<>();
List<String> insertcols = new ArrayList<>();
List<Attribute<T, ?>> insertattrs = new ArrayList<>();
List<Attribute<T, Serializable>> insertattrs = new ArrayList<>();
List<String> updatecols = new ArrayList<>();
List<Attribute<T, ?>> updateattrs = new ArrayList<>();
List<Attribute<T, Serializable>> updateattrs = new ArrayList<>();
boolean auto = false;
boolean sqldistribute = false;
int allocationSize0 = 0;
@@ -175,6 +177,7 @@ public final class EntityInfo<T> {
if (col == null || col.updatable()) {
updatecols.add(sqlfield);
updateattrs.add(attr);
updateAttributeMap.put(fieldname, attr);
}
}
queryattrs.add(attr);
@@ -248,10 +251,14 @@ public final class EntityInfo<T> {
return this.primary;
}
public Attribute<T, ?> getAttribute(String fieldname) {
public Attribute<T, Serializable> getAttribute(String fieldname) {
return this.attributes.get(fieldname);
}
public Attribute<T, Serializable> getUpdateAttribute(String fieldname) {
return this.updateAttributeMap.get(fieldname);
}
public boolean isNoAlias() {
return this.aliasmap == null;
}
@@ -266,7 +273,7 @@ public final class EntityInfo<T> {
return getSQLColumn(this.primary.field());
}
public Map<String, Attribute<T, ?>> getAttributes() {
public Map<String, Attribute<T, Serializable>> getAttributes() {
return attributes;
}
@@ -276,9 +283,9 @@ public final class EntityInfo<T> {
public T getValue(SelectColumn sels, ResultSet set) throws SQLException {
T obj = creator.create();
for (Attribute<T, Object> attr : queryAttributes) {
for (Attribute<T, Serializable> attr : queryAttributes) {
if (sels == null || sels.validate(attr.field())) {
Object o = set.getObject(this.getSQLColumn(attr.field()));
Serializable o = (Serializable) set.getObject(this.getSQLColumn(attr.field()));
if (o != null) {
if (type == long.class) {
o = ((Number) o).longValue();

View File

@@ -93,8 +93,8 @@ final class FilterInfo<T extends FilterBean> {
EntityInfo secinfo = EntityInfo.load(joinCol.table(), null);
if (!again) {
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.getPrimary().field() : joinCol.column());
.append(" ").append(alias).append(" ON a.# = ").append(alias).append(".")
.append(joinCol.column().isEmpty() ? secinfo.getPrimary().field() : joinCol.column());
}
}
getters.put(field.getName(), item);
@@ -157,30 +157,6 @@ final class FilterInfo<T extends FilterBean> {
return rootNode.getFilterPredicate(info, bean);
}
public static <E> Comparator<E> getSortComparator(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(",")) {
if (item.isEmpty()) continue;
String[] sub = item.split("\\s+");
final Attribute<E, ?> attr = info.getAttribute(sub[0]);
Comparator<E> c = (E o1, E o2) -> {
Comparable c1 = (Comparable) attr.get(o1);
Comparable c2 = (Comparable) attr.get(o2);
return c1 == null ? -1 : c1.compareTo(c2);
};
if (sub.length > 1 && sub[1].equalsIgnoreCase("DESC")) {
c = c.reversed();
}
if (comparator == null) {
comparator = c;
} else {
comparator = comparator.thenComparing(c);
}
}
return comparator;
}
public StringBuilder createWhereSql(String primaryColumn, T obj) {
StringBuilder sb = rootNode.getFilterExpress(obj);
if (sb == null) return null;
@@ -378,7 +354,7 @@ final class FilterInfo<T extends FilterBean> {
private StringBuilder getRangeExpress(Range range) {
StringBuilder sb = new StringBuilder();
return sb.append("(").append(aliasfield).append((NOTBETWEEN == express ? " NOT BETWEEN " : " BETWEEN "))
.append(formatToString(range.getMin())).append(" AND ").append(formatToString(range.getMax())).append(")");
.append(formatToString(range.getMin())).append(" AND ").append(formatToString(range.getMax())).append(")");
}
private <E> Predicate<E> getRangePredicate(final Attribute<E, ?> attr, Range range) {

View File

@@ -114,6 +114,49 @@ public class FilterNode {
return new FilterNode(column, express, value);
}
protected final <T> StringBuilder createFilterSQLExpress(final EntityInfo<T> info, FilterBean bean) {
final Serializable val = getValue(bean);
if (val == null && express != ISNULL && express != ISNOTNULL) return null;
StringBuilder sb0 = createFilterSQLExpress(info, val);
if (nodes == null) return sb0;
final StringBuilder rs = new StringBuilder();
rs.append('(');
if (sb0 != null) rs.append(sb0);
for (FilterNode node : this.nodes) {
StringBuilder f = node.createFilterSQLExpress(info, bean);
if (f == null) continue;
if (rs.length() > 0) rs.append(signand ? " AND " : " OR ");
rs.append(f);
}
rs.append(')');
if (rs.length() < 3) return null;
return rs;
}
private <T> StringBuilder createFilterSQLExpress(final EntityInfo<T> info, Serializable val0) {
final StringBuilder val = formatValue(val0);
if (val == null) return null;
StringBuilder sb = new StringBuilder();
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)");
break;
case OPANDNO:
sb.append(express.value()).append(' ').append(val).append(" = 0)");
break;
default:
sb.append(express.value()).append(' ').append(val);
break;
}
return sb;
}
protected final <T> Predicate<T> createFilterPredicate(final EntityInfo<T> info, FilterBean bean) {
if (info == null) return null;
final Serializable val = getValue(bean);
@@ -128,7 +171,7 @@ public class FilterNode {
return filter;
}
private <T> Predicate<T> createFilterPredicate(final Attribute<T, ?> attr, final Serializable val) {
private <T> Predicate<T> createFilterPredicate(final Attribute<T, Serializable> attr, final Serializable val) {
if (attr == null) return null;
switch (express) {
case EQUAL: return (T t) -> val.equals(attr.get(t));
@@ -218,13 +261,53 @@ public class FilterNode {
return null;
}
protected static String formatValue(Object value) {
if (value == null) return null;
if (value instanceof Number) return value.toString();
if (value instanceof CharSequence) {
return new StringBuilder().append('"').append(value.toString().replace("\"", "\\\"")).append('"').toString();
protected static <E> Comparator<E> getSortComparator(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(",")) {
if (item.isEmpty()) continue;
String[] sub = item.split("\\s+");
final Attribute<E, Serializable> attr = info.getAttribute(sub[0]);
Comparator<E> c = (E o1, E o2) -> {
Comparable c1 = (Comparable) attr.get(o1);
Comparable c2 = (Comparable) attr.get(o2);
return c1 == null ? -1 : c1.compareTo(c2);
};
if (sub.length > 1 && sub[1].equalsIgnoreCase("DESC")) {
c = c.reversed();
}
if (comparator == null) {
comparator = c;
} else {
comparator = comparator.thenComparing(c);
}
}
if (value.getClass().isArray()) {
return comparator;
}
protected StringBuilder formatValue(Object value) {
if (value == null) return null;
if (value instanceof Number) return new StringBuilder().append(value);
if (value instanceof CharSequence) {
if (express == LIKE || express == NOTLIKE) value = "%" + value + '%';
return new StringBuilder().append('\\').append(value.toString().replace("'", "\\'")).append('\'');
} else if (value instanceof Range) {
Range range = (Range) value;
boolean rangestring = range.getClass() == Range.StringRange.class;
StringBuilder sb = new StringBuilder();
if (rangestring) {
sb.append('\'').append(range.getMin().toString().replace("'", "\\'")).append('\'');
} else {
sb.append(range.getMin());
}
sb.append(" AND ");
if (rangestring) {
sb.append('\'').append(range.getMax().toString().replace("'", "\\'")).append('\'');
} else {
sb.append(range.getMax());
}
return sb;
} else if (value.getClass().isArray()) {
int len = Array.getLength(value);
if (len == 0) return null;
StringBuilder sb = new StringBuilder();
@@ -233,14 +316,13 @@ public class FilterNode {
Object o = Array.get(value, i);
if (sb.length() > 0) sb.append(',');
if (o instanceof CharSequence) {
sb.append('"').append(o.toString().replace("\"", "\\\"")).append('"');
sb.append('\'').append(o.toString().replace("'", "\\'")).append('\'');
} else {
sb.append(o);
}
}
return sb.append(')').toString();
}
if (value instanceof Collection) {
return sb.append(')');
} else if (value instanceof Collection) {
Collection c = (Collection) value;
if (c.isEmpty()) return null;
StringBuilder sb = new StringBuilder();
@@ -248,14 +330,14 @@ public class FilterNode {
for (Object o : c) {
if (sb.length() > 0) sb.append(',');
if (o instanceof CharSequence) {
sb.append('"').append(o.toString().replace("\"", "\\\"")).append('"');
sb.append('\'').append(o.toString().replace("'", "\\'")).append('\'');
} else {
sb.append(o);
}
}
return sb.append(')').toString();
return sb.append(')');
}
return String.valueOf(value);
return new StringBuilder().append(value);
}
@Override