From a3a21cb78351fc74387f99f2ff6979b3c856dbae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=9C=B0=E5=B9=B3=E7=BA=BF?= <22250530@qq.com> Date: Sun, 31 May 2015 11:40:07 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=B9=E7=89=88EntityXInfo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../wentch/redkale/source/DataJDBCSource.java | 34 +++--- .../wentch/redkale/source/EntityCache.java | 24 ++-- src/com/wentch/redkale/source/EntityInfo.java | 29 +++-- src/com/wentch/redkale/source/FilterInfo.java | 30 +---- src/com/wentch/redkale/source/FilterNode.java | 110 +++++++++++++++--- 5 files changed, 146 insertions(+), 81 deletions(-) diff --git a/src/com/wentch/redkale/source/DataJDBCSource.java b/src/com/wentch/redkale/source/DataJDBCSource.java index b6a2a9634..642c0cf63 100644 --- a/src/com/wentch/redkale/source/DataJDBCSource.java +++ b/src/com/wentch/redkale/source/DataJDBCSource.java @@ -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[] attrs = info.insertAttributes; + Attribute[] 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 attr : attrs) { + for (Attribute 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 attr : attrs) { + for (Attribute 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 cache = info.getCache(); if (cache == null) return; - final Attribute attr = info.getAttribute(column); + final Attribute 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 cache = info.getCache(); if (cache == null) return; - final Attribute attr1 = info.getAttribute(column1); - final Attribute attr2 = info.getAttribute(column2); + final Attribute attr1 = info.getAttribute(column1); + final Attribute 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 info = loadEntityInfo(clazz); if (debug.get()) logger.finest(clazz.getSimpleName() + " update sql=" + info.updateSQL); final PreparedStatement prestmt = conn.prepareStatement(info.updateSQL); - Attribute[] attrs = info.updateAttributes; + Attribute[] attrs = info.updateAttributes; String[] sqls = null; if (writeListener == null) { for (final T value : values) { int i = 0; - for (Attribute attr : attrs) { + for (Attribute 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 attr : attrs) { + for (Attribute 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 cache = info.getCache(); if (cache == null) return; - Attribute attr = (Attribute) info.getAttribute(column); + Attribute 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 clazz = (Class) value.getClass(); final EntityInfo info = loadEntityInfo(clazz); StringBuilder setsql = new StringBuilder(); - Attribute[] attrs = new Attribute[columns.length]; + Attribute[] 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 info = loadEntityInfo(clazz); final EntityCache cache = info.getCache(); if (cache != null) { - final Attribute attr1 = info.getAttribute(column1); - final Attribute attr2 = info.getAttribute(column2); + final Attribute attr1 = info.getAttribute(column1); + final Attribute 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 info = loadEntityInfo(clazz); final EntityCache cache = info.getCache(); if (cache != null) { - Attribute idattr = info.getAttribute(column); + Attribute idattr = info.getAttribute(column); List 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 Predicate genFilter(final Attribute attr, FilterExpress express, Serializable key) { + private Predicate genFilter(final Attribute attr, FilterExpress express, Serializable key) { Predicate 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 sheet = cache.querySheet(selects, filter, flipper, FilterInfo.getSortComparator(info, flipper)); + Sheet 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 getAttribute(String fieldname) { + public Attribute getAttribute(String fieldname) { return inner.getAttribute(fieldname); } } diff --git a/src/com/wentch/redkale/source/EntityCache.java b/src/com/wentch/redkale/source/EntityCache.java index ff8c14a8f..e3c269d0e 100644 --- a/src/com/wentch/redkale/source/EntityCache.java +++ b/src/com/wentch/redkale/source/EntityCache.java @@ -36,14 +36,14 @@ final class EntityCache { private final Attribute primary; //key是field的name - private final Map> attributes; + private final Map> attributes; private final Reproduce reproduce; private boolean fullloaded; public EntityCache(final Class type, Creator creator, - Attribute primary, Map> attributes) { + Attribute primary, Map> attributes) { this.type = type; this.creator = creator; this.primary = primary; @@ -63,7 +63,7 @@ final class EntityCache { public void fullLoad(List 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 { if (selects == null) { stream.forEach(x -> rs.add(needcopy ? reproduce.copy(creator.create(), x) : x)); } else { - final List> attrs = new ArrayList<>(); - for (Map.Entry> en : this.attributes.entrySet()) { + final List> attrs = new ArrayList<>(); + for (Map.Entry> en : this.attributes.entrySet()) { if (selects.validate(en.getKey())) attrs.add(en.getValue()); } stream.forEach(x -> { @@ -207,8 +207,8 @@ final class EntityCache { if (selects == null) { stream.forEach(x -> rs.add(needcopy ? reproduce.copy(creator.create(), x) : x)); } else { - final List> attrs = new ArrayList<>(); - for (Map.Entry> en : this.attributes.entrySet()) { + final List> attrs = new ArrayList<>(); + for (Map.Entry> en : this.attributes.entrySet()) { if (selects.validate(en.getKey())) attrs.add(en.getValue()); } stream.forEach(x -> { @@ -225,7 +225,7 @@ final class EntityCache { 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 { 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 { 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[] attrs) { + public void update(final T value, Attribute[] 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)); diff --git a/src/com/wentch/redkale/source/EntityInfo.java b/src/com/wentch/redkale/source/EntityInfo.java index 76aa0bc9c..fabb7217b 100644 --- a/src/com/wentch/redkale/source/EntityInfo.java +++ b/src/com/wentch/redkale/source/EntityInfo.java @@ -47,19 +47,21 @@ public final class EntityInfo { //key是field的name, 不是sql字段。 //存放所有与数据库对应的字段, 包括主键 - private final Map> attributes = new HashMap<>(); + private final Map> attributes = new HashMap<>(); + + private final Map> updateAttributeMap = new HashMap<>(); final String querySQL; - private final Attribute[] queryAttributes; //数据库中所有字段 + private final Attribute[] queryAttributes; //数据库中所有字段 final String insertSQL; - final Attribute[] insertAttributes; //数据库中所有可新增字段 + final Attribute[] insertAttributes; //数据库中所有可新增字段 final String updateSQL; - final Attribute[] updateAttributes; //数据库中所有可更新字段 + final Attribute[] updateAttributes; //数据库中所有可更新字段 final String deleteSQL; @@ -120,11 +122,11 @@ public final class EntityInfo { Map aliasmap0 = null; Class cltmp = type; Set fields = new HashSet<>(); - List> queryattrs = new ArrayList<>(); + List> queryattrs = new ArrayList<>(); List insertcols = new ArrayList<>(); - List> insertattrs = new ArrayList<>(); + List> insertattrs = new ArrayList<>(); List updatecols = new ArrayList<>(); - List> updateattrs = new ArrayList<>(); + List> updateattrs = new ArrayList<>(); boolean auto = false; boolean sqldistribute = false; int allocationSize0 = 0; @@ -175,6 +177,7 @@ public final class EntityInfo { 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 { return this.primary; } - public Attribute getAttribute(String fieldname) { + public Attribute getAttribute(String fieldname) { return this.attributes.get(fieldname); } + public Attribute getUpdateAttribute(String fieldname) { + return this.updateAttributeMap.get(fieldname); + } + public boolean isNoAlias() { return this.aliasmap == null; } @@ -266,7 +273,7 @@ public final class EntityInfo { return getSQLColumn(this.primary.field()); } - public Map> getAttributes() { + public Map> getAttributes() { return attributes; } @@ -276,9 +283,9 @@ public final class EntityInfo { public T getValue(SelectColumn sels, ResultSet set) throws SQLException { T obj = creator.create(); - for (Attribute attr : queryAttributes) { + for (Attribute 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(); diff --git a/src/com/wentch/redkale/source/FilterInfo.java b/src/com/wentch/redkale/source/FilterInfo.java index d62c9344d..67bdd69e4 100644 --- a/src/com/wentch/redkale/source/FilterInfo.java +++ b/src/com/wentch/redkale/source/FilterInfo.java @@ -93,8 +93,8 @@ final class FilterInfo { 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 { return rootNode.getFilterPredicate(info, bean); } - public static Comparator getSortComparator(EntityInfo info, Flipper flipper) { - if (flipper == null || flipper.getSort() == null || flipper.getSort().isEmpty()) return null; - Comparator comparator = null; - for (String item : flipper.getSort().split(",")) { - if (item.isEmpty()) continue; - String[] sub = item.split("\\s+"); - final Attribute attr = info.getAttribute(sub[0]); - Comparator 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 { 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 Predicate getRangePredicate(final Attribute attr, Range range) { diff --git a/src/com/wentch/redkale/source/FilterNode.java b/src/com/wentch/redkale/source/FilterNode.java index 9c1a669d2..f024159f0 100644 --- a/src/com/wentch/redkale/source/FilterNode.java +++ b/src/com/wentch/redkale/source/FilterNode.java @@ -114,6 +114,49 @@ public class FilterNode { return new FilterNode(column, express, value); } + protected final StringBuilder createFilterSQLExpress(final EntityInfo 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 StringBuilder createFilterSQLExpress(final EntityInfo 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 Predicate createFilterPredicate(final EntityInfo info, FilterBean bean) { if (info == null) return null; final Serializable val = getValue(bean); @@ -128,7 +171,7 @@ public class FilterNode { return filter; } - private Predicate createFilterPredicate(final Attribute attr, final Serializable val) { + private Predicate createFilterPredicate(final Attribute 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 Comparator getSortComparator(EntityInfo info, Flipper flipper) { + if (flipper == null || flipper.getSort() == null || flipper.getSort().isEmpty()) return null; + Comparator comparator = null; + for (String item : flipper.getSort().split(",")) { + if (item.isEmpty()) continue; + String[] sub = item.split("\\s+"); + final Attribute attr = info.getAttribute(sub[0]); + Comparator 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