From 00a37fb2631ad7e26bbba441d6ca4d74b8765dc3 Mon Sep 17 00:00:00 2001 From: redkale Date: Wed, 16 Aug 2023 15:45:15 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0nativeQuerySheet=E6=96=B9?= =?UTF-8?q?=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../redkale/source/AbstractDataSqlSource.java | 7 +- .../org/redkale/source/DataJdbcSource.java | 117 +++++++++++++++--- .../redkale/source/DataNativeSqlParser.java | 13 +- .../org/redkale/source/DataSqlSource.java | 69 ++++------- .../org/redkale/source/EntityBuilder.java | 23 ++++ 5 files changed, 167 insertions(+), 62 deletions(-) diff --git a/src/main/java/org/redkale/source/AbstractDataSqlSource.java b/src/main/java/org/redkale/source/AbstractDataSqlSource.java index 3db009880..521f581b4 100644 --- a/src/main/java/org/redkale/source/AbstractDataSqlSource.java +++ b/src/main/java/org/redkale/source/AbstractDataSqlSource.java @@ -648,7 +648,7 @@ public abstract class AbstractDataSqlSource extends AbstractDataSource implement if (nativeSqlParser == null) { throw new SourceException("not found DataNativeSqlParser instance"); } - return nativeSqlParser.parse(signFunc, nativeSql, params == null ? Collections.emptyMap() : params); + return nativeSqlParser.parse(signFunc, dbtype(), nativeSql, params == null ? Collections.emptyMap() : params); } @Override @@ -3243,6 +3243,11 @@ public abstract class AbstractDataSqlSource extends AbstractDataSource implement return nativeQueryAsync(sql, consumer, handler).join(); } + @Override + public Sheet nativeQuerySheet(Class type, String sql, Flipper flipper, Map params) { + return nativeQuerySheetAsync(type, sql, flipper, params).join(); + } + @Override public int nativeUpdate(String sql, Map params) { return nativeUpdateAsync(sql, params).join(); diff --git a/src/main/java/org/redkale/source/DataJdbcSource.java b/src/main/java/org/redkale/source/DataJdbcSource.java index 9cd5624cb..99663ca79 100644 --- a/src/main/java/org/redkale/source/DataJdbcSource.java +++ b/src/main/java/org/redkale/source/DataJdbcSource.java @@ -2328,16 +2328,10 @@ public class DataJdbcSource extends AbstractDataSqlSource { private Sheet executeQuerySheet(EntityInfo info, boolean needTotal, Flipper flipper, SelectColumn sels, long s, SourceConnection conn, boolean mysqlOrPgsql, String listSql, String countSql) throws SQLException { final List list = new ArrayList(); - if (mysqlOrPgsql) { //sql可以带limit、offset - PreparedStatement prestmt = conn.prepareQueryStatement(listSql); - ResultSet set = prestmt.executeQuery(); - final DataResultSet rr = createDataResultSet(info, set); - while (set.next()) { - list.add(getEntityValue(info, sels, rr)); - } - set.close(); - conn.offerQueryStatement(prestmt); - long total = list.size(); + if (mysqlOrPgsql) { //sql可以带limit、offset + ResultSet set; + PreparedStatement prestmt; + long total = -1; if (needTotal) { prestmt = conn.prepareQueryStatement(countSql); set = prestmt.executeQuery(); @@ -2347,6 +2341,19 @@ public class DataJdbcSource extends AbstractDataSqlSource { set.close(); conn.offerQueryStatement(prestmt); } + if (total != 0) { + prestmt = conn.prepareQueryStatement(listSql); + set = prestmt.executeQuery(); + final DataResultSet rr = createDataResultSet(info, set); + while (set.next()) { + list.add(getEntityValue(info, sels, rr)); + } + set.close(); + conn.offerQueryStatement(prestmt); + if (!needTotal) { + total = list.size(); + } + } slowLog(s, listSql); return new Sheet<>(total, list); } else { @@ -2548,10 +2555,10 @@ public class DataJdbcSource extends AbstractDataSqlSource { int rs; if (sinfo.isEmptyNamed()) { final Statement stmt = conn.createUpdateStatement(); - rs = stmt.executeUpdate(sinfo.nativeSql); + rs = stmt.executeUpdate(sinfo.getNativeSql()); conn.offerUpdateStatement(stmt); } else { - final PreparedStatement prestmt = conn.prepareQueryStatement(sinfo.nativeSql); + final PreparedStatement prestmt = conn.prepareQueryStatement(sinfo.getNativeSql()); Map paramValues = sinfo.getParamValues(); int index = 0; for (String n : sinfo.getParamNames()) { @@ -2622,7 +2629,7 @@ public class DataJdbcSource extends AbstractDataSqlSource { final SourceConnection conn = readPool.pollConnection(); try { if (logger.isLoggable(Level.FINEST)) { - logger.finest("executeQuery sql=" + sinfo.nativeSql); + logger.finest("executeQuery sql=" + sinfo.getNativeSql()); } V rs; if (sinfo.isEmptyNamed()) { @@ -2630,12 +2637,12 @@ public class DataJdbcSource extends AbstractDataSqlSource { if (consumer != null) { consumer.accept(conn, stmt); } - ResultSet set = stmt.executeQuery(sql); + ResultSet set = stmt.executeQuery(sinfo.getNativeSql()); rs = handler.apply(createDataResultSet(null, set)); set.close(); conn.offerQueryStatement(stmt); } else { - final PreparedStatement prestmt = conn.prepareQueryStatement(sinfo.nativeSql); + final PreparedStatement prestmt = conn.prepareQueryStatement(sinfo.getNativeSql()); Map paramValues = sinfo.getParamValues(); int index = 0; for (String n : sinfo.getParamNames()) { @@ -2644,12 +2651,12 @@ public class DataJdbcSource extends AbstractDataSqlSource { if (consumer != null) { consumer.accept(conn, prestmt); } - ResultSet set = prestmt.executeQuery(sql); + ResultSet set = prestmt.executeQuery(); rs = handler.apply(createDataResultSet(null, set)); set.close(); conn.offerQueryStatement(prestmt); } - slowLog(s, sql); + slowLog(s, sinfo.getNativeSql()); return rs; } catch (Exception ex) { throw new SourceException(ex); @@ -2660,6 +2667,77 @@ public class DataJdbcSource extends AbstractDataSqlSource { } } + public Sheet nativeQuerySheet(Class type, String sql, Flipper flipper, Map params) { + final boolean mysqlOrPgsql = "mysql".equals(dbtype()) || "postgresql".equals(dbtype()); + NativeSqlStatement sinfo = super.nativeParse(sql, params); + final long s = System.currentTimeMillis(); + final SourceConnection conn = readPool.pollConnection(); + try { + if (logger.isLoggable(Level.FINEST)) { + logger.finest("executeQuery sql=" + sinfo.nativeSql); + } + long total = -1; + List list; + if (sinfo.isEmptyNamed()) { + Statement stmt = conn.createQueryStatement(); + ResultSet set = stmt.executeQuery(sinfo.getNativeCountSql()); + if (set.next()) { + total = set.getLong(1); + }; + set.close(); + conn.offerQueryStatement(stmt); + } else { + final PreparedStatement prestmt = conn.prepareQueryStatement(sinfo.getNativeCountSql()); + Map paramValues = sinfo.getParamValues(); + int index = 0; + for (String n : sinfo.getParamNames()) { + prestmt.setObject(++index, paramValues.get(n)); + } + ResultSet set = prestmt.executeQuery(); + if (set.next()) { + total = set.getLong(1); + }; + set.close(); + conn.offerQueryStatement(prestmt); + } + slowLog(s, sinfo.getNativeCountSql()); + if (total > 0) { + String listSql = sinfo.getNativeSql(); + if (mysqlOrPgsql) { + listSql += (flipper == null || flipper.getLimit() < 1 ? "" : (" LIMIT " + flipper.getLimit() + " OFFSET " + flipper.getOffset())); + } + if (sinfo.isEmptyNamed()) { + Statement stmt = conn.createQueryStatement(); + ResultSet set = stmt.executeQuery(listSql); + list = EntityBuilder.getListValue(type, createDataResultSet(null, set)); + set.close(); + conn.offerQueryStatement(stmt); + } else { + final PreparedStatement prestmt = conn.prepareQueryStatement(listSql); + Map paramValues = sinfo.getParamValues(); + int index = 0; + for (String n : sinfo.getParamNames()) { + prestmt.setObject(++index, paramValues.get(n)); + } + ResultSet set = prestmt.executeQuery(); + list = EntityBuilder.getListValue(type, createDataResultSet(null, set)); + set.close(); + conn.offerQueryStatement(prestmt); + } + slowLog(s, listSql); + } else { + list = new ArrayList(); + } + return new Sheet<>(total, list); + } catch (Exception ex) { + throw new SourceException(ex); + } finally { + if (conn != null) { + readPool.offerConnection(conn); + } + } + } + @Override public CompletableFuture nativeQueryAsync(String sql, BiConsumer consumer, Function handler, Map params) { return supplyAsync(() -> nativeQuery(sql, consumer, handler, params)); @@ -2685,6 +2763,11 @@ public class DataJdbcSource extends AbstractDataSqlSource { return supplyAsync(() -> nativeUpdates(sqls)); } + @Override + public CompletableFuture> nativeQuerySheetAsync(Class type, String sql, Flipper flipper, Map params) { + return supplyAsync(() -> nativeQuerySheet(type, sql, flipper, params)); + } + @Deprecated public int directExecute(String sql) { return nativeUpdate(sql); diff --git a/src/main/java/org/redkale/source/DataNativeSqlParser.java b/src/main/java/org/redkale/source/DataNativeSqlParser.java index a5739f76a..ebe57fbc6 100644 --- a/src/main/java/org/redkale/source/DataNativeSqlParser.java +++ b/src/main/java/org/redkale/source/DataNativeSqlParser.java @@ -20,13 +20,16 @@ import org.redkale.convert.json.JsonConvert; */ public interface DataNativeSqlParser { - NativeSqlStatement parse(Function signFunc, String nativeSql, Map params); + NativeSqlStatement parse(Function signFunc, String dbtype, String nativeSql, Map params); public static class NativeSqlStatement { //根据参数值集合重新生成的带?参数可执行的sql protected String nativeSql; + //根据参数值集合重新生成的带?参数可执行的计算总数sql,用于返回Sheet对象 + protected String nativeCountSql; + //是否包含InExpression参数名 protected boolean existInNamed; @@ -54,6 +57,14 @@ public interface DataNativeSqlParser { this.nativeSql = nativeSql; } + public String getNativeCountSql() { + return nativeCountSql; + } + + public void setNativeCountSql(String nativeCountSql) { + this.nativeCountSql = nativeCountSql; + } + public boolean isExistInNamed() { return existInNamed; } diff --git a/src/main/java/org/redkale/source/DataSqlSource.java b/src/main/java/org/redkale/source/DataSqlSource.java index 01b88e49b..c61b19089 100644 --- a/src/main/java/org/redkale/source/DataSqlSource.java +++ b/src/main/java/org/redkale/source/DataSqlSource.java @@ -8,7 +8,7 @@ import java.util.*; import java.util.concurrent.CompletableFuture; import java.util.function.*; import static org.redkale.source.DataResultSet.formatColumnValue; -import org.redkale.util.Copier; +import org.redkale.util.*; /** * @@ -128,6 +128,10 @@ public interface DataSqlSource extends DataSource { */ public CompletableFuture nativeQueryAsync(String sql, BiConsumer consumer, Function handler, Map params); + public Sheet nativeQuerySheet(Class type, String sql, Flipper flipper, Map params); + + public CompletableFuture> nativeQuerySheetAsync(Class type, String sql, Flipper flipper, Map params); + //----------------------------- 无参数 ----------------------------- default V nativeQuery(String sql, Function handler) { return nativeQuery(sql, null, handler); @@ -138,57 +142,27 @@ public interface DataSqlSource extends DataSource { } default V nativeQueryOne(Class type, String sql) { - return nativeQuery(sql, rset -> { - if (!rset.next()) { - return null; - } - if (type == byte[].class || type == String.class || type.isPrimitive() || Number.class.isAssignableFrom(type) - || (!Map.class.isAssignableFrom(type) && type.getName().startsWith("java."))) { - return (V) formatColumnValue(type, rset.getObject(1)); - } - return EntityBuilder.load(type).getObjectValue(rset); - }); + return nativeQuery(sql, rset -> EntityBuilder.getOneValue(type, rset)); } default CompletableFuture nativeQueryOneAsync(Class type, String sql) { - return nativeQueryAsync(sql, rset -> { - if (!rset.next()) { - return null; - } - if (type == byte[].class || type == String.class || type.isPrimitive() || Number.class.isAssignableFrom(type) - || (!Map.class.isAssignableFrom(type) && type.getName().startsWith("java."))) { - return (V) formatColumnValue(type, rset.getObject(1)); - } - return EntityBuilder.load(type).getObjectValue(rset); - }); + return nativeQueryAsync(sql, rset -> EntityBuilder.getOneValue(type, rset)); } default List nativeQueryList(Class type, String sql) { - return nativeQuery(sql, rset -> { - if (type == byte[].class || type == String.class || type.isPrimitive() || Number.class.isAssignableFrom(type) - || (!Map.class.isAssignableFrom(type) && type.getName().startsWith("java."))) { - List list = new ArrayList<>(); - while (rset.next()) { - list.add(rset.wasNull() ? null : (V) formatColumnValue(type, rset.getObject(1))); - } - return list; - } - return EntityBuilder.load(type).getObjectList(rset); - }); + return nativeQuery(sql, rset -> EntityBuilder.getListValue(type, rset)); } default CompletableFuture> nativeQueryListAsync(Class type, String sql) { - return nativeQueryAsync(sql, rset -> { - if (type == byte[].class || type == String.class || type.isPrimitive() || Number.class.isAssignableFrom(type) - || (!Map.class.isAssignableFrom(type) && type.getName().startsWith("java."))) { - List list = new ArrayList<>(); - while (rset.next()) { - list.add(rset.wasNull() ? null : (V) formatColumnValue(type, rset.getObject(1))); - } - return list; - } - return EntityBuilder.load(type).getObjectList(rset); - }); + return nativeQueryAsync(sql, rset -> EntityBuilder.getListValue(type, rset)); + } + + default Sheet nativeQuerySheet(Class type, String sql, Flipper flipper) { + return nativeQuerySheet(type, sql, flipper, Collections.emptyMap()); + } + + default CompletableFuture> nativeQuerySheetAsync(Class type, String sql, Flipper flipper) { + return nativeQuerySheetAsync(type, sql, flipper, Collections.emptyMap()); } default Map nativeQueryMap(Class keyType, Class valType, String sql) { @@ -390,4 +364,13 @@ public interface DataSqlSource extends DataSource { default CompletableFuture> nativeQueryIntStrMapAsync(String sql, Serializable bean) { return nativeQueryMapAsync(Integer.class, String.class, sql, (Map) Copier.copyToMap(bean, Copier.OPTION_SKIP_NULL_VALUE)); } + + default Sheet nativeQuerySheet(Class type, String sql, Flipper flipper, Serializable bean) { + return nativeQuerySheet(type, sql, flipper, (Map) Copier.copyToMap(bean, Copier.OPTION_SKIP_NULL_VALUE)); + } + + default CompletableFuture> nativeQuerySheetAsync(Class type, String sql, Flipper flipper, Serializable bean) { + return nativeQuerySheetAsync(type, sql, flipper, (Map) Copier.copyToMap(bean, Copier.OPTION_SKIP_NULL_VALUE)); + } + } diff --git a/src/main/java/org/redkale/source/EntityBuilder.java b/src/main/java/org/redkale/source/EntityBuilder.java index 6faec5d45..1796ac703 100644 --- a/src/main/java/org/redkale/source/EntityBuilder.java +++ b/src/main/java/org/redkale/source/EntityBuilder.java @@ -183,6 +183,29 @@ public class EntityBuilder { unconstructorAttributes, attributeMap, queryAttrs.toArray(new Attribute[queryAttrs.size()])); } + public static List getListValue(Class type, final DataResultSet rset) { + if (type == byte[].class || type == String.class || type.isPrimitive() || Number.class.isAssignableFrom(type) + || (!Map.class.isAssignableFrom(type) && type.getName().startsWith("java."))) { + List list = new ArrayList<>(); + while (rset.next()) { + list.add(rset.wasNull() ? null : (T) DataResultSet.formatColumnValue(type, rset.getObject(1))); + } + return list; + } + return EntityBuilder.load(type).getObjectList(rset); + } + + public static T getOneValue(Class type, final DataResultSet rset) { + if (!rset.next()) { + return null; + } + if (type == byte[].class || type == String.class || type.isPrimitive() || Number.class.isAssignableFrom(type) + || (!Map.class.isAssignableFrom(type) && type.getName().startsWith("java."))) { + return (T) DataResultSet.formatColumnValue(type, rset.getObject(1)); + } + return EntityBuilder.load(type).getObjectValue(rset); + } + public List getObjectList(final DataResultSet rset) { List list = new ArrayList<>(); List sqlColumns = rset.getColumnLabels();