EntityBuilder支持Map类型
This commit is contained in:
@@ -35,7 +35,7 @@ public interface DataSqlSource extends DataSource {
|
|||||||
if (!rset.next()) {
|
if (!rset.next()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (type.isPrimitive() || type == byte[].class || type.getName().startsWith("java.")) {
|
if (type.isPrimitive() || type == byte[].class || (!Map.class.isAssignableFrom(type) && type.getName().startsWith("java."))) {
|
||||||
return (V) formatColumnValue(type, rset.getObject(1));
|
return (V) formatColumnValue(type, rset.getObject(1));
|
||||||
}
|
}
|
||||||
return EntityBuilder.load(type).getObjectValue(rset);
|
return EntityBuilder.load(type).getObjectValue(rset);
|
||||||
@@ -44,7 +44,7 @@ public interface DataSqlSource extends DataSource {
|
|||||||
|
|
||||||
default <V> List<V> nativeQueryList(Class<V> type, String sql) {
|
default <V> List<V> nativeQueryList(Class<V> type, String sql) {
|
||||||
return nativeQuery(sql, rset -> {
|
return nativeQuery(sql, rset -> {
|
||||||
if (type.isPrimitive() || type == byte[].class || type.getName().startsWith("java.")) {
|
if (type.isPrimitive() || type == byte[].class || (!Map.class.isAssignableFrom(type) && type.getName().startsWith("java."))) {
|
||||||
List<V> list = new ArrayList<>();
|
List<V> list = new ArrayList<>();
|
||||||
while (rset.next()) {
|
while (rset.next()) {
|
||||||
list.add(rset.wasNull() ? null : (V) formatColumnValue(type, rset.getObject(1)));
|
list.add(rset.wasNull() ? null : (V) formatColumnValue(type, rset.getObject(1)));
|
||||||
|
|||||||
@@ -23,6 +23,12 @@ public class EntityBuilder<T> {
|
|||||||
|
|
||||||
private static final ConcurrentHashMap<Class, EntityBuilder> cacheMap = new ConcurrentHashMap<>();
|
private static final ConcurrentHashMap<Class, EntityBuilder> cacheMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
//实体类名
|
||||||
|
private final Class<T> type;
|
||||||
|
|
||||||
|
//是否Map类型的虚拟实体类
|
||||||
|
private final boolean entityIsMap;
|
||||||
|
|
||||||
//Entity构建器
|
//Entity构建器
|
||||||
private final Creator<T> creator;
|
private final Creator<T> creator;
|
||||||
|
|
||||||
@@ -52,12 +58,13 @@ public class EntityBuilder<T> {
|
|||||||
//数据库中所有字段, 顺序必须与querySqlColumns、querySqlColumnSequence一致
|
//数据库中所有字段, 顺序必须与querySqlColumns、querySqlColumnSequence一致
|
||||||
private final Attribute<T, Serializable>[] attributes;
|
private final Attribute<T, Serializable>[] attributes;
|
||||||
|
|
||||||
EntityBuilder(Creator<T> creator,
|
EntityBuilder(Class<T> type, Creator<T> creator,
|
||||||
Map<String, String> aliasmap, String[] constructorParameters,
|
Map<String, String> aliasmap, String[] constructorParameters,
|
||||||
Attribute<T, Serializable>[] constructorAttributes,
|
Attribute<T, Serializable>[] constructorAttributes,
|
||||||
Attribute<T, Serializable>[] unconstructorAttributes,
|
Attribute<T, Serializable>[] unconstructorAttributes,
|
||||||
Map<String, Attribute<T, Serializable>> attributeMap,
|
Map<String, Attribute<T, Serializable>> attributeMap,
|
||||||
Attribute<T, Serializable>[] queryAttributes) {
|
Attribute<T, Serializable>[] queryAttributes) {
|
||||||
|
this.type = type;
|
||||||
this.creator = creator;
|
this.creator = creator;
|
||||||
this.aliasmap = aliasmap;
|
this.aliasmap = aliasmap;
|
||||||
this.constructorParameters = constructorParameters;
|
this.constructorParameters = constructorParameters;
|
||||||
@@ -66,6 +73,7 @@ public class EntityBuilder<T> {
|
|||||||
this.attributeMap = attributeMap;
|
this.attributeMap = attributeMap;
|
||||||
this.attributes = queryAttributes;
|
this.attributes = queryAttributes;
|
||||||
this.sqlAttrMap = new HashMap<>();
|
this.sqlAttrMap = new HashMap<>();
|
||||||
|
this.entityIsMap = Map.class.isAssignableFrom(type);
|
||||||
attributeMap.forEach((k, v) -> sqlAttrMap.put(getSQLColumn(null, k), v));
|
attributeMap.forEach((k, v) -> sqlAttrMap.put(getSQLColumn(null, k), v));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,66 +84,70 @@ public class EntityBuilder<T> {
|
|||||||
private static <T> EntityBuilder<T> create(Class<T> type) {
|
private static <T> EntityBuilder<T> create(Class<T> type) {
|
||||||
Creator<T> creator = Creator.create(type);
|
Creator<T> creator = Creator.create(type);
|
||||||
String[] constructorParameters = null;
|
String[] constructorParameters = null;
|
||||||
try {
|
if (!Map.class.isAssignableFrom(type)) {
|
||||||
Method cm = creator.getClass().getMethod("create", Object[].class);
|
try {
|
||||||
RedkaleClassLoader.putReflectionPublicMethods(creator.getClass().getName());
|
Method cm = creator.getClass().getMethod("create", Object[].class);
|
||||||
RedkaleClassLoader.putReflectionMethod(creator.getClass().getName(), cm);
|
RedkaleClassLoader.putReflectionPublicMethods(creator.getClass().getName());
|
||||||
org.redkale.annotation.ConstructorParameters cp = cm.getAnnotation(org.redkale.annotation.ConstructorParameters.class);
|
RedkaleClassLoader.putReflectionMethod(creator.getClass().getName(), cm);
|
||||||
if (cp != null && cp.value().length > 0) {
|
org.redkale.annotation.ConstructorParameters cp = cm.getAnnotation(org.redkale.annotation.ConstructorParameters.class);
|
||||||
constructorParameters = cp.value();
|
if (cp != null && cp.value().length > 0) {
|
||||||
} else {
|
constructorParameters = cp.value();
|
||||||
org.redkale.util.ConstructorParameters cp2 = cm.getAnnotation(org.redkale.util.ConstructorParameters.class);
|
} else {
|
||||||
if (cp2 != null && cp2.value().length > 0) {
|
org.redkale.util.ConstructorParameters cp2 = cm.getAnnotation(org.redkale.util.ConstructorParameters.class);
|
||||||
constructorParameters = cp2.value();
|
if (cp2 != null && cp2.value().length > 0) {
|
||||||
|
constructorParameters = cp2.value();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new SourceException(type + " cannot find ConstructorParameters Creator");
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
|
||||||
throw new SourceException(type + " cannot find ConstructorParameters Creator");
|
|
||||||
}
|
}
|
||||||
Class cltmp = type;
|
Class cltmp = type;
|
||||||
Map<String, String> aliasmap = null;
|
Map<String, String> aliasmap = null;
|
||||||
Set<String> fields = new HashSet<>();
|
Set<String> fields = new HashSet<>();
|
||||||
List<Attribute<T, Serializable>> queryAttrs = new ArrayList<>();
|
List<Attribute<T, Serializable>> queryAttrs = new ArrayList<>();
|
||||||
HashMap<String, Attribute<T, Serializable>> attributeMap = new HashMap<>();
|
HashMap<String, Attribute<T, Serializable>> attributeMap = new HashMap<>();
|
||||||
do {
|
if (!Map.class.isAssignableFrom(type)) {
|
||||||
RedkaleClassLoader.putReflectionDeclaredFields(cltmp.getName());
|
do {
|
||||||
for (Field field : cltmp.getDeclaredFields()) {
|
RedkaleClassLoader.putReflectionDeclaredFields(cltmp.getName());
|
||||||
if (Modifier.isStatic(field.getModifiers())) {
|
for (Field field : cltmp.getDeclaredFields()) {
|
||||||
continue;
|
if (Modifier.isStatic(field.getModifiers())) {
|
||||||
}
|
continue;
|
||||||
if (Modifier.isFinal(field.getModifiers())) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (field.getAnnotation(Transient.class) != null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (field.getAnnotation(javax.persistence.Transient.class) != null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (fields.contains(field.getName())) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
final String fieldName = field.getName();
|
|
||||||
final Column col = field.getAnnotation(Column.class);
|
|
||||||
final String sqlField = col == null || col.name().isEmpty() ? fieldName : col.name();
|
|
||||||
if (!fieldName.equals(sqlField)) {
|
|
||||||
if (aliasmap == null) {
|
|
||||||
aliasmap = new HashMap<>();
|
|
||||||
}
|
}
|
||||||
aliasmap.put(fieldName, sqlField);
|
if (Modifier.isFinal(field.getModifiers())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (field.getAnnotation(Transient.class) != null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (field.getAnnotation(javax.persistence.Transient.class) != null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (fields.contains(field.getName())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
final String fieldName = field.getName();
|
||||||
|
final Column col = field.getAnnotation(Column.class);
|
||||||
|
final String sqlField = col == null || col.name().isEmpty() ? fieldName : col.name();
|
||||||
|
if (!fieldName.equals(sqlField)) {
|
||||||
|
if (aliasmap == null) {
|
||||||
|
aliasmap = new HashMap<>();
|
||||||
|
}
|
||||||
|
aliasmap.put(fieldName, sqlField);
|
||||||
|
}
|
||||||
|
Attribute attr;
|
||||||
|
try {
|
||||||
|
attr = Attribute.create(type, cltmp, field);
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
RedkaleClassLoader.putReflectionField(cltmp.getName(), field);
|
||||||
|
queryAttrs.add(attr);
|
||||||
|
fields.add(fieldName);
|
||||||
|
attributeMap.put(fieldName, attr);
|
||||||
}
|
}
|
||||||
Attribute attr;
|
} while ((cltmp = cltmp.getSuperclass()) != Object.class);
|
||||||
try {
|
}
|
||||||
attr = Attribute.create(type, cltmp, field);
|
|
||||||
} catch (RuntimeException e) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
RedkaleClassLoader.putReflectionField(cltmp.getName(), field);
|
|
||||||
queryAttrs.add(attr);
|
|
||||||
fields.add(fieldName);
|
|
||||||
attributeMap.put(fieldName, attr);
|
|
||||||
}
|
|
||||||
} while ((cltmp = cltmp.getSuperclass()) != Object.class);
|
|
||||||
Attribute<T, Serializable>[] constructorAttributes;
|
Attribute<T, Serializable>[] constructorAttributes;
|
||||||
Attribute<T, Serializable>[] unconstructorAttributes;
|
Attribute<T, Serializable>[] unconstructorAttributes;
|
||||||
if (constructorParameters == null) {
|
if (constructorParameters == null) {
|
||||||
@@ -144,8 +156,8 @@ public class EntityBuilder<T> {
|
|||||||
} else {
|
} else {
|
||||||
constructorAttributes = new Attribute[constructorParameters.length];
|
constructorAttributes = new Attribute[constructorParameters.length];
|
||||||
List<Attribute<T, Serializable>> unconstructorAttrs = new ArrayList<>();
|
List<Attribute<T, Serializable>> unconstructorAttrs = new ArrayList<>();
|
||||||
List<String> newquerycols1 = new ArrayList<>();
|
List<String> newQueryCols1 = new ArrayList<>();
|
||||||
List<String> newquerycols2 = new ArrayList<>();
|
List<String> newQueryCols2 = new ArrayList<>();
|
||||||
for (Attribute<T, Serializable> attr : new ArrayList<>(queryAttrs)) {
|
for (Attribute<T, Serializable> attr : new ArrayList<>(queryAttrs)) {
|
||||||
int pos = -1;
|
int pos = -1;
|
||||||
for (int i = 0; i < constructorParameters.length; i++) {
|
for (int i = 0; i < constructorParameters.length; i++) {
|
||||||
@@ -161,13 +173,13 @@ public class EntityBuilder<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
unconstructorAttributes = unconstructorAttrs.toArray(new Attribute[unconstructorAttrs.size()]);
|
unconstructorAttributes = unconstructorAttrs.toArray(new Attribute[unconstructorAttrs.size()]);
|
||||||
newquerycols1.addAll(newquerycols2);
|
newQueryCols1.addAll(newQueryCols2);
|
||||||
List<Attribute<T, Serializable>> newqueryattrs = new ArrayList<>();
|
List<Attribute<T, Serializable>> newQueryAttrs = new ArrayList<>();
|
||||||
newqueryattrs.addAll(List.of(constructorAttributes));
|
newQueryAttrs.addAll(List.of(constructorAttributes));
|
||||||
newqueryattrs.addAll(unconstructorAttrs);
|
newQueryAttrs.addAll(unconstructorAttrs);
|
||||||
queryAttrs = newqueryattrs;
|
queryAttrs = newQueryAttrs;
|
||||||
}
|
}
|
||||||
return new EntityBuilder<>(creator, aliasmap, constructorParameters, constructorAttributes,
|
return new EntityBuilder<>(type, creator, aliasmap, constructorParameters, constructorAttributes,
|
||||||
unconstructorAttributes, attributeMap, queryAttrs.toArray(new Attribute[queryAttrs.size()]));
|
unconstructorAttributes, attributeMap, queryAttrs.toArray(new Attribute[queryAttrs.size()]));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -192,6 +204,14 @@ public class EntityBuilder<T> {
|
|||||||
if (sqlColumns == null) {
|
if (sqlColumns == null) {
|
||||||
sqlColumns = row.getColumnLabels();
|
sqlColumns = row.getColumnLabels();
|
||||||
}
|
}
|
||||||
|
if (entityIsMap) {
|
||||||
|
final Map map = (Map) creator.create();
|
||||||
|
obj = (T) map;
|
||||||
|
for (String sqlCol : sqlColumns) {
|
||||||
|
map.put(sqlCol, getFieldValue(row, sqlCol));
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
Map<String, Attribute<T, Serializable>> attrs = this.sqlAttrMap;
|
Map<String, Attribute<T, Serializable>> attrs = this.sqlAttrMap;
|
||||||
if (this.constructorParameters == null) {
|
if (this.constructorParameters == null) {
|
||||||
obj = creator.create();
|
obj = creator.create();
|
||||||
@@ -241,6 +261,13 @@ public class EntityBuilder<T> {
|
|||||||
if (row.wasNull()) {
|
if (row.wasNull()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
if (entityIsMap) {
|
||||||
|
final Map map = (Map) creator.create();
|
||||||
|
for (String sqlCol : row.getColumnLabels()) {
|
||||||
|
map.put(sqlCol, getFieldValue(row, sqlCol));
|
||||||
|
}
|
||||||
|
return (T) map;
|
||||||
|
}
|
||||||
T obj;
|
T obj;
|
||||||
Attribute<T, Serializable>[] attrs = this.attributes;
|
Attribute<T, Serializable>[] attrs = this.attributes;
|
||||||
if (this.constructorParameters == null) {
|
if (this.constructorParameters == null) {
|
||||||
@@ -293,6 +320,13 @@ public class EntityBuilder<T> {
|
|||||||
if (row.wasNull()) {
|
if (row.wasNull()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
if (entityIsMap) {
|
||||||
|
final Map map = (Map) creator.create();
|
||||||
|
for (String sqlCol : row.getColumnLabels()) {
|
||||||
|
map.put(sqlCol, getFieldValue(row, sqlCol));
|
||||||
|
}
|
||||||
|
return (T) map;
|
||||||
|
}
|
||||||
T obj;
|
T obj;
|
||||||
int index = 0;
|
int index = 0;
|
||||||
if (this.constructorParameters == null) {
|
if (this.constructorParameters == null) {
|
||||||
@@ -358,6 +392,10 @@ public class EntityBuilder<T> {
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected Serializable getFieldValue(final DataResultSetRow row, String sqlColumn) {
|
||||||
|
return (Serializable) row.getObject(sqlColumn);
|
||||||
|
}
|
||||||
|
|
||||||
protected Serializable getFieldValue(Attribute<T, Serializable> attr, final DataResultSetRow row, int index) {
|
protected Serializable getFieldValue(Attribute<T, Serializable> attr, final DataResultSetRow row, int index) {
|
||||||
return row.getObject(attr, index, index > 0 ? null : this.getSQLColumn(null, attr.field()));
|
return row.getObject(attr, index, index > 0 ? null : this.getSQLColumn(null, attr.field()));
|
||||||
}
|
}
|
||||||
@@ -394,4 +432,8 @@ public class EntityBuilder<T> {
|
|||||||
return creator;
|
return creator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ConvertDisabled
|
||||||
|
public Class<T> getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -565,7 +565,7 @@ public final class EntityInfo<T> {
|
|||||||
String field = this.queryAttributes[i].field();
|
String field = this.queryAttributes[i].field();
|
||||||
this.queryColumns[i] = Utility.find(this.ddlColumns, c -> c.field.equals(field));
|
this.queryColumns[i] = Utility.find(this.ddlColumns, c -> c.field.equals(field));
|
||||||
}
|
}
|
||||||
this.builder = new EntityBuilder<>(creator, aliasmap, constructorParameters, constructorAttributes, unconstructorAttributes, attributeMap, queryAttributes);
|
this.builder = new EntityBuilder<>(type, creator, aliasmap, constructorParameters, constructorAttributes, unconstructorAttributes, attributeMap, queryAttributes);
|
||||||
|
|
||||||
if (table != null) {
|
if (table != null) {
|
||||||
StringBuilder querydb = new StringBuilder();
|
StringBuilder querydb = new StringBuilder();
|
||||||
|
|||||||
Reference in New Issue
Block a user