diff --git a/src/main/java/org/redkale/source/DataJdbcSource.java b/src/main/java/org/redkale/source/DataJdbcSource.java index e5d871599..c9cc04ba6 100644 --- a/src/main/java/org/redkale/source/DataJdbcSource.java +++ b/src/main/java/org/redkale/source/DataJdbcSource.java @@ -2465,7 +2465,7 @@ public class DataJdbcSource extends AbstractDataSqlSource { final SourceConnection conn = readPool.pollConnection(); try { if (logger.isLoggable(Level.FINEST)) { - logger.finest("direct query sql=" + sql); + logger.finest("executeQuery sql=" + sql); } final Statement stmt = conn.createQueryStatement(); //final PreparedStatement prestmt = conn.prepareStatement(sql); diff --git a/src/main/java/org/redkale/source/DataResultSet.java b/src/main/java/org/redkale/source/DataResultSet.java index ae6a83e55..5396f294a 100644 --- a/src/main/java/org/redkale/source/DataResultSet.java +++ b/src/main/java/org/redkale/source/DataResultSet.java @@ -6,6 +6,7 @@ package org.redkale.source; import java.io.Serializable; +import java.lang.reflect.Type; import java.math.*; import java.nio.charset.StandardCharsets; import java.util.concurrent.atomic.*; @@ -45,6 +46,117 @@ public interface DataResultSet extends EntityInfo.DataResultSetRow { public void close(); + public static Serializable formatColumnValue(Class t, Object o) { + return formatColumnValue(t, null, o); + } + + public static Serializable formatColumnValue(Class t, Type genericType, Object o) { + if (t == byte[].class) { + return (byte[]) o; + } else { + if (t.isPrimitive()) { + if (o != null) { + if (t == int.class) { + o = ((Number) o).intValue(); + } else if (t == long.class) { + o = ((Number) o).longValue(); + } else if (t == short.class) { + o = ((Number) o).shortValue(); + } else if (t == float.class) { + o = ((Number) o).floatValue(); + } else if (t == double.class) { + o = ((Number) o).doubleValue(); + } else if (t == byte.class) { + o = ((Number) o).byteValue(); + } else if (t == char.class) { + o = (char) ((Number) o).intValue(); + } else if (t == boolean.class) { + o = (Boolean) o; + } + } else if (t == int.class) { + o = 0; + } else if (t == long.class) { + o = 0L; + } else if (t == short.class) { + o = (short) 0; + } else if (t == float.class) { + o = 0.0f; + } else if (t == double.class) { + o = 0.0d; + } else if (t == byte.class) { + o = (byte) 0; + } else if (t == boolean.class) { + o = false; + } else if (t == char.class) { + o = (char) 0; + } + } else if (t == Integer.class) { + o = ((Number) o).intValue(); + } else if (t == Long.class) { + o = ((Number) o).longValue(); + } else if (t == Short.class) { + o = ((Number) o).shortValue(); + } else if (t == Float.class) { + o = ((Number) o).floatValue(); + } else if (t == Double.class) { + o = ((Number) o).doubleValue(); + } else if (t == Byte.class) { + o = ((Number) o).byteValue(); + } else if (t == Character.class) { + o = (char) ((Number) o).intValue(); + } else if (t == Boolean.class) { + o = (Boolean) o; + } else if (t == AtomicInteger.class) { + if (o != null) { + o = new AtomicInteger(((Number) o).intValue()); + } else { + o = new AtomicInteger(); + } + } else if (t == AtomicLong.class) { + if (o != null) { + o = new AtomicLong(((Number) o).longValue()); + } else { + o = new AtomicLong(); + } + } else if (t == LongAdder.class) { + if (o != null) { + LongAdder v = new LongAdder(); + v.add(((Number) o).longValue()); + o = v; + } else { + o = new LongAdder(); + } + } else if (t == BigInteger.class) { + if (o != null && !(o instanceof BigInteger)) { + if (o instanceof byte[]) { + o = new BigInteger((byte[]) o); + } else { + o = new BigInteger(o.toString(), 10); + } + } + } else if (t == BigDecimal.class) { + if (o != null && !(o instanceof BigDecimal)) { + if (o instanceof byte[]) { + o = new BigDecimal(new String((byte[]) o)); + } else { + o = new BigDecimal(o.toString()); + } + } + } else if (t == String.class) { + if (o == null) { + o = ""; + } else if (o instanceof byte[]) { + o = new String((byte[]) o, StandardCharsets.UTF_8); + } else { + o = o.toString(); + } + } else if (o != null && !t.isAssignableFrom(o.getClass()) && o instanceof CharSequence) { + o = ((CharSequence) o).length() == 0 ? null : JsonConvert.root().convertFrom(genericType == null ? t : genericType, o.toString()); + } + } + return (Serializable) o; + } + public static Serializable getRowColumnValue(final EntityInfo.DataResultSetRow row, Attribute attr, int index, String column) { final Class t = attr.type(); Serializable o = null; @@ -67,89 +179,7 @@ public interface DataResultSet extends EntityInfo.DataResultSetRow { } } else { o = (Serializable) (index > 0 ? row.getObject(index) : row.getObject(column)); - if (t.isPrimitive()) { - if (o != null) { - if (t == int.class) { - o = ((Number) o).intValue(); - } else if (t == long.class) { - o = ((Number) o).longValue(); - } else if (t == short.class) { - o = ((Number) o).shortValue(); - } else if (t == float.class) { - o = ((Number) o).floatValue(); - } else if (t == double.class) { - o = ((Number) o).doubleValue(); - } else if (t == byte.class) { - o = ((Number) o).byteValue(); - } else if (t == char.class) { - o = (char) ((Number) o).intValue(); - } else if (t == boolean.class) { - o = (Boolean) o; - } - } else if (t == int.class) { - o = 0; - } else if (t == long.class) { - o = 0L; - } else if (t == short.class) { - o = (short) 0; - } else if (t == float.class) { - o = 0.0f; - } else if (t == double.class) { - o = 0.0d; - } else if (t == byte.class) { - o = (byte) 0; - } else if (t == boolean.class) { - o = false; - } else if (t == char.class) { - o = (char) 0; - } - } else if (t == AtomicInteger.class) { - if (o != null) { - o = new AtomicInteger(((Number) o).intValue()); - } else { - o = new AtomicInteger(); - } - } else if (t == AtomicLong.class) { - if (o != null) { - o = new AtomicLong(((Number) o).longValue()); - } else { - o = new AtomicLong(); - } - } else if (t == LongAdder.class) { - if (o != null) { - LongAdder v = new LongAdder(); - v.add(((Number) o).longValue()); - o = v; - } else { - o = new LongAdder(); - } - } else if (t == BigInteger.class) { - if (o != null && !(o instanceof BigInteger)) { - if (o instanceof byte[]) { - o = new BigInteger((byte[]) o); - } else { - o = new BigInteger(o.toString(), 10); - } - } - } else if (t == BigDecimal.class) { - if (o != null && !(o instanceof BigDecimal)) { - if (o instanceof byte[]) { - o = new BigDecimal(new String((byte[]) o)); - } else { - o = new BigDecimal(o.toString()); - } - } - } else if (t == String.class) { - if (o == null) { - o = ""; - } else if (o instanceof byte[]) { - o = new String((byte[]) o, StandardCharsets.UTF_8); - } else { - o = o.toString(); - } - } else if (o != null && !t.isAssignableFrom(o.getClass()) && o instanceof CharSequence) { - o = ((CharSequence) o).length() == 0 ? null : JsonConvert.root().convertFrom(attr.genericType(), o.toString()); - } + o = formatColumnValue(t, attr.genericType(), o); } } catch (Exception e) { throw new SourceException(row.getEntityInfo() + "." + attr.field() + ".value=" + o + ": " + e.getMessage(), e.getCause()); diff --git a/src/main/java/org/redkale/source/DataSqlSource.java b/src/main/java/org/redkale/source/DataSqlSource.java index 0aaf422d9..dccff133a 100644 --- a/src/main/java/org/redkale/source/DataSqlSource.java +++ b/src/main/java/org/redkale/source/DataSqlSource.java @@ -3,6 +3,7 @@ */ package org.redkale.source; +import java.util.*; import java.util.function.Function; /** @@ -23,4 +24,28 @@ public interface DataSqlSource extends DataSource { public V executeQuery(String sql, Function handler); + default V executeQueryOne(Class type, String sql) { + return executeQuery(sql, rset -> { + if (!rset.next()) { + return null; + } + if (type.isPrimitive() || type == byte[].class || type.getName().startsWith("java.")) { + return (V) DataResultSet.formatColumnValue(type, rset.getObject(1)); + } + return EntityBuilder.load(type).getObjectValue(rset); + }); + } + + default List executeQueryList(Class type, String sql) { + return executeQuery(sql, rset -> { + if (type.isPrimitive() || type == byte[].class || type.getName().startsWith("java.")) { + List list = new ArrayList<>(); + while (rset.next()) { + list.add(rset.wasNull() ? null : (V) DataResultSet.formatColumnValue(type, rset.getObject(1))); + } + return list; + } + return EntityBuilder.load(type).getObjectList(rset); + }); + } } diff --git a/src/main/java/org/redkale/source/EntityBuilder.java b/src/main/java/org/redkale/source/EntityBuilder.java index 53c98445c..9e1fd6707 100644 --- a/src/main/java/org/redkale/source/EntityBuilder.java +++ b/src/main/java/org/redkale/source/EntityBuilder.java @@ -10,6 +10,7 @@ import java.util.concurrent.ConcurrentHashMap; import org.redkale.annotation.Nullable; import org.redkale.convert.ConvertDisabled; import org.redkale.persistence.*; +import org.redkale.source.EntityInfo.DataResultSetRow; import org.redkale.util.*; /** @@ -29,7 +30,7 @@ public class EntityBuilder { @Nullable private final String[] constructorParameters; - //key是field的name, value是Column的别名,即数据库表的字段名 + //key:类字段名, value:数据库字段名 //只有field.name 与 Column.name不同才存放在aliasmap里. @Nullable private final Map aliasmap; @@ -42,7 +43,11 @@ public class EntityBuilder { @Nullable private final Attribute[] unconstructorAttributes; - private final HashMap> attributeMap; + //key:类字段名 + private final Map> attributeMap; + + //key:数据库字段名 + private final Map> sqlAttrMap; //数据库中所有字段, 顺序必须与querySqlColumns、querySqlColumnSequence一致 private final Attribute[] attributes; @@ -51,7 +56,7 @@ public class EntityBuilder { Map aliasmap, String[] constructorParameters, Attribute[] constructorAttributes, Attribute[] unconstructorAttributes, - HashMap> attributeMap, + Map> attributeMap, Attribute[] queryAttributes) { this.creator = creator; this.aliasmap = aliasmap; @@ -60,6 +65,8 @@ public class EntityBuilder { this.unconstructorAttributes = unconstructorAttributes; this.attributeMap = attributeMap; this.attributes = queryAttributes; + this.sqlAttrMap = new HashMap<>(); + attributeMap.forEach((k, v) -> sqlAttrMap.put(getSQLColumn(null, k), v)); } public static EntityBuilder load(Class type) { @@ -164,6 +171,64 @@ public class EntityBuilder { unconstructorAttributes, attributeMap, queryAttrs.toArray(new Attribute[queryAttrs.size()])); } + public List getObjectList(final DataResultSet rset) { + List list = new ArrayList<>(); + List sqlColumns = rset.getColumnLabels(); + while (rset.next()) { + list.add(getObjectValue(sqlColumns, rset)); + } + return list; + } + + public T getObjectValue(final DataResultSetRow row) { + return getObjectValue(null, row); + } + + protected T getObjectValue(List sqlColumns, final DataResultSetRow row) { + if (row.wasNull()) { + return null; + } + T obj; + if (sqlColumns == null) { + sqlColumns = row.getColumnLabels(); + } + Map> attrs = this.sqlAttrMap; + if (this.constructorParameters == null) { + obj = creator.create(); + for (String sqlCol : sqlColumns) { + Attribute attr = attrs.get(sqlCol); + if (attr != null) { //兼容返回的字段不存在类中 + attr.set(obj, getFieldValue(attr, row, 0)); + } + } + } else { + Object[] cps = new Object[this.constructorParameters.length]; + for (int i = 0; i < this.constructorAttributes.length; i++) { + Attribute attr = this.constructorAttributes[i]; + String sqlCol = getSQLColumn(null, attr.field()); + if (sqlColumns.contains(sqlCol)) { + cps[i] = getFieldValue(attr, row, 0); + } + } + obj = creator.create(cps); + for (Attribute attr : this.unconstructorAttributes) { + String sqlCol = getSQLColumn(null, attr.field()); + if (sqlColumns.contains(sqlCol)) { + attr.set(obj, getFieldValue(attr, row, 0)); + } + } + } + return obj; + } + + public List getEntityList(final SelectColumn sels, final DataResultSet rset) { + List list = new ArrayList<>(); + while (rset.next()) { + list.add(getEntityValue(sels, rset)); + } + return list; + } + /** * 将一行的ResultSet组装成一个Entity对象 * @@ -172,7 +237,7 @@ public class EntityBuilder { * * @return Entity对象 */ - public T getEntityValue(final SelectColumn sels, final EntityInfo.DataResultSetRow row) { + public T getEntityValue(final SelectColumn sels, final DataResultSetRow row) { if (row.wasNull()) { return null; } @@ -199,7 +264,15 @@ public class EntityBuilder { return obj; } - public T getFullEntityValue(final EntityInfo.DataResultSetRow row) { + public List getFullEntityList(final DataResultSet rset) { + List list = new ArrayList<>(); + while (rset.next()) { + list.add(getFullEntityValue(rset)); + } + return list; + } + + public T getFullEntityValue(final DataResultSetRow row) { return getEntityValue(constructorAttributes, constructorAttributes == null ? attributes : unconstructorAttributes, row); } @@ -216,7 +289,7 @@ public class EntityBuilder { * * @return Entity对象 */ - protected T getEntityValue(final Attribute[] constructorAttrs, final Attribute[] unconstructorAttrs, final EntityInfo.DataResultSetRow row) { + protected T getEntityValue(final Attribute[] constructorAttrs, final Attribute[] unconstructorAttrs, final DataResultSetRow row) { if (row.wasNull()) { return null; } @@ -285,7 +358,7 @@ public class EntityBuilder { return obj; } - protected Serializable getFieldValue(Attribute attr, final EntityInfo.DataResultSetRow row, int index) { + protected Serializable getFieldValue(Attribute attr, final DataResultSetRow row, int index) { return row.getObject(attr, index, index > 0 ? null : this.getSQLColumn(null, attr.field())); }