This commit is contained in:
地平线
2015-05-26 17:56:45 +08:00
parent 5a4a7006f1
commit a365d7c59c
8 changed files with 225 additions and 39 deletions

View File

@@ -1007,7 +1007,7 @@ public final class DataJDBCSource implements DataSource {
final EntityCache<T> cache = info.inner.getCache();
if (cache == null) return;
for (Serializable id : ids) {
T value = find(clazz, false, id);
T value = find(clazz, null, false, id);
if (value != null) cache.update(value);
}
}
@@ -1064,7 +1064,7 @@ public final class DataJDBCSource implements DataSource {
@Override
public Number getCountDistinctSingleResult(final Class entityClass, String column, FilterBean bean) {
return getSingleResult(ReckonType.COUNT, entityClass, true, column, bean);
return getSingleResult(ReckonType.DISTINCTCOUNT, entityClass, column, bean);
}
//-----------------------------AVG-----------------------------
@@ -1079,14 +1079,21 @@ public final class DataJDBCSource implements DataSource {
}
private <T> Number getSingleResult(final ReckonType type, final Class<T> entityClass, final String column, FilterBean bean) {
return getSingleResult(type, entityClass, false, column, bean);
}
private <T> Number getSingleResult(final ReckonType type, final Class<T> entityClass, final boolean distinct, final String column, FilterBean bean) {
final Connection conn = createReadSQLConnection();
try {
final EntityXInfo<T> info = EntityXInfo.load(this, entityClass);
final String sql = "SELECT " + type.getReckonColumn((distinct ? "DISTINCT " : "") + "a." + column) + " FROM " + info.getTable() + " a" + createWhereExpression(info, null, bean);
final EntityCache<T> cache = info.inner.getCache();
if (cache != null && cache.isFullLoaded()) {
Predicate<T> filter = null;
boolean valid = true;
if (bean != null) {
FilterInfo finfo = FilterInfo.load(bean.getClass(), this);
valid = finfo.isValidCacheJoin();
if (valid) filter = finfo.getFilterPredicate(info.inner, bean);
}
if (valid) return cache.getSingleResult(type, column == null ? null : info.getAttribute(column), filter);
}
final String sql = "SELECT " + type.getReckonColumn("a." + column) + " FROM " + info.getTable() + " a" + createWhereExpression(info, null, bean);
if (debug.get() && info.isLoggable(Level.FINEST)) logger.finest(entityClass.getSimpleName() + " single sql=" + sql);
final PreparedStatement prestmt = conn.prepareStatement(sql);
Number rs = null;
@@ -1115,10 +1122,15 @@ public final class DataJDBCSource implements DataSource {
*/
@Override
public <T> T find(Class<T> clazz, Serializable pk) {
return find(clazz, true, pk);
return find(clazz, null, true, pk);
}
private <T> T find(Class<T> clazz, boolean readcache, Serializable pk) {
@Override
public <T> T find(Class<T> clazz, final SelectColumn selects, Serializable pk) {
return find(clazz, selects, true, pk);
}
private <T> T find(Class<T> clazz, final SelectColumn selects, boolean readcache, Serializable pk) {
final EntityXInfo<T> info = EntityXInfo.load(this, clazz);
final EntityCache<T> cache = info.inner.getCache();
if (readcache && cache != null) {
@@ -1134,8 +1146,8 @@ public final class DataJDBCSource implements DataSource {
ResultSet set = prestmt.executeQuery();
if (set.next()) {
rs = info.createInstance();
for (Attribute attr : info.query.attributes) {
attr.set(rs, set.getObject(attr.field()));
for (AttributeX attr : info.query.attributes) {
attr.setValue(selects, rs, set);
}
}
set.close();
@@ -2033,13 +2045,16 @@ public final class DataJDBCSource implements DataSource {
//----------------------------------------------------------------------
private static class AttributeX<T, F> implements Attribute<T, F> {
private final Class clazz;
private final Class type;
private final Attribute<T, F> attribute;
private final String fieldName;
public AttributeX(Class type, Attribute<T, F> attribute, String fieldname) {
public AttributeX(Class clazz, Class type, Attribute<T, F> attribute, String fieldname) {
this.clazz = clazz;
this.type = type;
this.attribute = attribute;
this.fieldName = fieldname;
@@ -2050,6 +2065,11 @@ public final class DataJDBCSource implements DataSource {
return type;
}
@Override
public Class declaringClass() {
return clazz;
}
@Override
public String field() {
return attribute.field();
@@ -2090,6 +2110,7 @@ public final class DataJDBCSource implements DataSource {
attribute.set(obj, (F) o);
}
}
}
private static class EntityXInfo<T> {
@@ -2178,7 +2199,7 @@ public final class DataJDBCSource implements DataSource {
final Class fieldtype = field.getType();
Attribute attribute = inner.getAttribute(fieldname);
if (attribute == null) continue;
AttributeX attr = new AttributeX(fieldtype, attribute, fieldname);
AttributeX attr = new AttributeX(cltmp, fieldtype, attribute, fieldname);
if (field.getAnnotation(Id.class) != null) {
idfieldtype = fieldtype;
GeneratedValue gv = field.getAnnotation(GeneratedValue.class);
@@ -2212,7 +2233,7 @@ public final class DataJDBCSource implements DataSource {
queryattrs.add(attr);
}
} while ((cltmp = cltmp.getSuperclass()) != Object.class);
AttributeX idxattr = new AttributeX(idfieldtype, inner.getPrimary(), inner.getPrimaryField());
AttributeX idxattr = new AttributeX(type, idfieldtype, inner.getPrimary(), inner.getPrimaryField());
updateattrs.add(idxattr);
this.autoGenerated = auto;
this.delete = new ActionInfo("DELETE FROM " + inner.getTable() + wheresql, idxattr);
@@ -2299,13 +2320,4 @@ public final class DataJDBCSource implements DataSource {
}
}
private static enum ReckonType {
MAX, MIN, SUM, COUNT, AVG;
public String getReckonColumn(String col) {
if (this == COUNT && !col.contains("DISTINCT")) return this.name() + "(*)";
return this.name() + "(" + col + ")";
}
}
}

View File

@@ -119,6 +119,11 @@ final class DataJPASource implements DataSource {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public <T> T find(Class<T> clazz, SelectColumn selects, Serializable pk) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
private static class DataJPAConnection extends DataConnection {
private final EntityManager manager;

View File

@@ -263,6 +263,17 @@ public interface DataSource {
*/
public <T> T find(Class<T> clazz, Serializable pk);
/**
* 根据主键获取对象
*
* @param <T>
* @param clazz
* @param selects
* @param pk
* @return
*/
public <T> T find(Class<T> clazz, final SelectColumn selects, Serializable pk);
/**
* 根据主键值集合获取对象集合
*

View File

@@ -96,8 +96,73 @@ final class EntityCache<T> {
return rs.isPresent() ? (needcopy ? reproduce.copy(this.creator.create(), rs.get()) : rs.get()) : null;
}
public <V> Number getSingleResult(final ReckonType type, final Attribute<T, V> attr, final Predicate<T> filter) {
Stream<T> stream = listStream();
if (filter != null) stream = stream.filter(filter);
switch (type) {
case AVG:
if (attr.type() == int.class || attr.type() == Integer.class) {
return (int) stream.mapToInt(x -> (Integer) attr.get(x)).average().orElse(0);
} else if (attr.type() == long.class || attr.type() == Long.class) {
return (long) stream.mapToLong(x -> (Long) attr.get(x)).average().orElse(0);
} else if (attr.type() == short.class || attr.type() == Short.class) {
return (short) stream.mapToInt(x -> ((Short) attr.get(x)).intValue()).average().orElse(0);
} else if (attr.type() == float.class || attr.type() == Float.class) {
return (float) stream.mapToDouble(x -> ((Float) attr.get(x)).doubleValue()).average().orElse(0);
} else if (attr.type() == double.class || attr.type() == Double.class) {
return stream.mapToDouble(x -> (Double) attr.get(x)).average().orElse(0);
}
throw new RuntimeException("getSingleResult error(type:" + type + ", attr.declaringClass: " + attr.declaringClass() + ", attr.field: " + attr.field() + ", attr.type: " + attr.type());
case COUNT: return stream.count();
case DISTINCTCOUNT: return stream.map(x -> attr.get(x)).distinct().count();
case MAX:
if (attr.type() == int.class || attr.type() == Integer.class) {
return stream.mapToInt(x -> (Integer) attr.get(x)).max().orElse(0);
} else if (attr.type() == long.class || attr.type() == Long.class) {
return stream.mapToLong(x -> (Long) attr.get(x)).max().orElse(0);
} else if (attr.type() == short.class || attr.type() == Short.class) {
return (short) stream.mapToInt(x -> ((Short) attr.get(x)).intValue()).max().orElse(0);
} else if (attr.type() == float.class || attr.type() == Float.class) {
return (float) stream.mapToDouble(x -> ((Float) attr.get(x)).doubleValue()).max().orElse(0);
} else if (attr.type() == double.class || attr.type() == Double.class) {
return stream.mapToDouble(x -> (Double) attr.get(x)).max().orElse(0);
}
throw new RuntimeException("getSingleResult error(type:" + type + ", attr.declaringClass: " + attr.declaringClass() + ", attr.field: " + attr.field() + ", attr.type: " + attr.type());
case MIN:
if (attr.type() == int.class || attr.type() == Integer.class) {
return stream.mapToInt(x -> (Integer) attr.get(x)).min().orElse(0);
} else if (attr.type() == long.class || attr.type() == Long.class) {
return stream.mapToLong(x -> (Long) attr.get(x)).min().orElse(0);
} else if (attr.type() == short.class || attr.type() == Short.class) {
return (short) stream.mapToInt(x -> ((Short) attr.get(x)).intValue()).min().orElse(0);
} else if (attr.type() == float.class || attr.type() == Float.class) {
return (float) stream.mapToDouble(x -> ((Float) attr.get(x)).doubleValue()).min().orElse(0);
} else if (attr.type() == double.class || attr.type() == Double.class) {
return stream.mapToDouble(x -> (Double) attr.get(x)).min().orElse(0);
}
throw new RuntimeException("getSingleResult error(type:" + type + ", attr.declaringClass: " + attr.declaringClass() + ", attr.field: " + attr.field() + ", attr.type: " + attr.type());
case SUM:
if (attr.type() == int.class || attr.type() == Integer.class) {
return stream.mapToInt(x -> (Integer) attr.get(x)).sum();
} else if (attr.type() == long.class || attr.type() == Long.class) {
return stream.mapToLong(x -> (Long) attr.get(x)).sum();
} else if (attr.type() == short.class || attr.type() == Short.class) {
return (short) stream.mapToInt(x -> ((Short) attr.get(x)).intValue()).sum();
} else if (attr.type() == float.class || attr.type() == Float.class) {
return (float) stream.mapToDouble(x -> ((Float) attr.get(x)).doubleValue()).sum();
} else if (attr.type() == double.class || attr.type() == Double.class) {
return stream.mapToDouble(x -> (Double) attr.get(x)).sum();
}
throw new RuntimeException("getSingleResult error(type:" + type + ", attr.declaringClass: " + attr.declaringClass() + ", attr.field: " + attr.field() + ", attr.type: " + attr.type());
}
return -1;
}
public Collection<T> queryCollection(final boolean set, final SelectColumn selects, final Predicate<T> filter, final Comparator<T> sort) {
boolean parallel = isParallel();
final boolean parallel = isParallel();
final Collection<T> rs = parallel ? (set ? new CopyOnWriteArraySet<>() : new CopyOnWriteArrayList<>()) : (set ? new LinkedHashSet<>() : new ArrayList<>());
Stream<T> stream = listStream();
if (filter != null) stream = stream.filter(filter);
@@ -105,12 +170,14 @@ final class EntityCache<T> {
if (selects == null) {
stream.forEach(x -> rs.add(needcopy ? reproduce.copy(creator.create(), x) : x));
} else {
final Map<String, Attribute<T, ?>> attrs = this.attributes;
final List<Attribute<T, ?>> attrs = new ArrayList<>();
for (Map.Entry<String, Attribute<T, ?>> en : this.attributes.entrySet()) {
if (selects.validate(en.getKey())) attrs.add(en.getValue());
}
stream.forEach(x -> {
final T item = creator.create();
for (Map.Entry<String, Attribute<T, ?>> en : attrs.entrySet()) {
Attribute attr = en.getValue();
if (selects.validate(en.getKey())) attr.set(item, attr.get(x));
for (Attribute attr : attrs) {
attr.set(item, attr.get(x));
}
rs.add(item);
});
@@ -142,12 +209,14 @@ final class EntityCache<T> {
if (selects == null) {
stream.forEach(x -> rs.add(needcopy ? reproduce.copy(creator.create(), x) : x));
} else {
final Map<String, Attribute<T, ?>> attrs = this.attributes;
final List<Attribute<T, ?>> attrs = new ArrayList<>();
for (Map.Entry<String, Attribute<T, ?>> en : this.attributes.entrySet()) {
if (selects.validate(en.getKey())) attrs.add(en.getValue());
}
stream.forEach(x -> {
final T item = creator.create();
for (Map.Entry<String, Attribute<T, ?>> en : attrs.entrySet()) {
Attribute attr = en.getValue();
if (selects.validate(en.getKey())) attr.set(item, attr.get(x));
for (Attribute attr : attrs) {
attr.set(item, attr.get(x));
}
rs.add(item);
});

View File

@@ -92,7 +92,7 @@ public final class EntityInfo<T> {
continue;
}
if (field.getAnnotation(javax.persistence.Id.class) != null) {
idAttr0 = attr;
if (idAttr0 == null) idAttr0 = attr;
primaryType0 = field.getType();
primaryName = field.getName();
}

View File

@@ -0,0 +1,21 @@
/*
* 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;
/**
*
* @author zhangjx
*/
public enum ReckonType {
AVG, COUNT, DISTINCTCOUNT, MAX, MIN, SUM;
public String getReckonColumn(String col) {
if (this == COUNT) return this.name() + "(*)";
if (this == DISTINCTCOUNT) return "COUNT(DISTINCT " + col + ")";
return this.name() + "(" + col + ")";
}
}

View File

@@ -5,7 +5,7 @@
*/
package com.wentch.redkale.source;
import java.util.Arrays;
import java.util.*;
/**
*
@@ -13,6 +13,10 @@ import java.util.Arrays;
*/
public final class SelectColumn {
private String[] startWithColumns;
private String[] endWithColumns;
private String[] columns;
private boolean excludable; //是否排除
@@ -20,9 +24,52 @@ public final class SelectColumn {
public SelectColumn() {
}
private SelectColumn(String[] columns, boolean excludable) {
this.columns = columns;
private SelectColumn(String[] columns0, boolean excludable) {
this.excludable = excludable;
final int len = columns0.length;
if (len < 1) return;
boolean reg = false;
int slen = 0, elen = 0;
for (String col : columns0) {
if (col.charAt(0) == '^') {
slen++;
reg = true;
} else if (col.charAt(col.length() - 1) == '$') {
elen++;
reg = true;
}
}
if (reg) {
if (slen == len) {
this.startWithColumns = new String[len];
for (int i = 0; i < len; i++) {
this.startWithColumns[i] = columns0[i].substring(1);
}
} else if (elen == len) {
this.endWithColumns = new String[len];
for (int i = 0; i < len; i++) {
this.endWithColumns[i] = columns0[i].substring(0, columns0[i].length() - 1);
}
} else {
List<String> starts = new ArrayList<>();
List<String> ends = new ArrayList<>();
List<String> strings = new ArrayList<>();
for (String col : columns0) {
if (col.charAt(0) == '^') {
starts.add(col.substring(1));
} else if (col.charAt(col.length() - 1) == '$') {
ends.add(col.substring(0, col.length() - 1));
} else {
strings.add(col);
}
}
if (!starts.isEmpty()) this.startWithColumns = starts.toArray(new String[starts.size()]);
if (!ends.isEmpty()) this.endWithColumns = ends.toArray(new String[ends.size()]);
if (!strings.isEmpty()) this.columns = strings.toArray(new String[strings.size()]);
}
} else {
this.columns = columns0;
}
}
/**
@@ -46,8 +93,20 @@ public final class SelectColumn {
}
public boolean validate(String column) {
for (String col : this.columns) {
if (col.equalsIgnoreCase(column)) return !excludable;
if (this.columns != null) {
for (String col : this.columns) {
if (col.equalsIgnoreCase(column)) return !excludable;
}
}
if (this.startWithColumns != null) {
for (String col : this.startWithColumns) {
if (column.startsWith(col)) return !excludable;
}
}
if (this.endWithColumns != null) {
for (String col : this.endWithColumns) {
if (column.endsWith(col)) return !excludable;
}
}
return excludable;
}

View File

@@ -21,6 +21,8 @@ public interface Attribute<T, F> {
public Class type();
public Class declaringClass();
public String field();
public F get(T obj);
@@ -64,7 +66,7 @@ public interface Attribute<T, F> {
}
@SuppressWarnings("unchecked")
public static <T, F> Attribute<T, F> create(Class<T> clazz, String fieldalias0, final Field field0, Method getter0, Method setter0) {
public static <T, F> Attribute<T, F> create(final Class<T> clazz, String fieldalias0, final Field field0, Method getter0, Method setter0) {
if (fieldalias0.isEmpty()) fieldalias0 = null;
int mod = field0 == null ? Modifier.STATIC : field0.getModifiers();
if (field0 != null && !Modifier.isStatic(mod) && !Modifier.isPublic(mod)) {
@@ -185,6 +187,13 @@ public interface Attribute<T, F> {
mv.visitMaxs(1, 1);
mv.visitEnd();
}
{ //declaringClass 方法
mv = cw.visitMethod(ACC_PUBLIC, "declaringClass", "()Ljava/lang/Class;", null, null);
mv.visitLdcInsn(Type.getType(clazz));
mv.visitInsn(ARETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
}
{ //get 方法
mv = cw.visitMethod(ACC_PUBLIC, "get", "(" + interDesc + ")" + columnDesc, null, null);
int m = 1;