增加nativeQuerySheet方法

This commit is contained in:
redkale
2023-08-16 15:45:15 +08:00
parent 8130eea859
commit 00a37fb263
5 changed files with 167 additions and 62 deletions

View File

@@ -648,7 +648,7 @@ public abstract class AbstractDataSqlSource extends AbstractDataSource implement
if (nativeSqlParser == null) { if (nativeSqlParser == null) {
throw new SourceException("not found DataNativeSqlParser instance"); 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 @Override
@@ -3243,6 +3243,11 @@ public abstract class AbstractDataSqlSource extends AbstractDataSource implement
return nativeQueryAsync(sql, consumer, handler).join(); return nativeQueryAsync(sql, consumer, handler).join();
} }
@Override
public <V> Sheet<V> nativeQuerySheet(Class<V> type, String sql, Flipper flipper, Map<String, Object> params) {
return nativeQuerySheetAsync(type, sql, flipper, params).join();
}
@Override @Override
public int nativeUpdate(String sql, Map<String, Object> params) { public int nativeUpdate(String sql, Map<String, Object> params) {
return nativeUpdateAsync(sql, params).join(); return nativeUpdateAsync(sql, params).join();

View File

@@ -2329,15 +2329,9 @@ public class DataJdbcSource extends AbstractDataSqlSource {
long s, SourceConnection conn, boolean mysqlOrPgsql, String listSql, String countSql) throws SQLException { long s, SourceConnection conn, boolean mysqlOrPgsql, String listSql, String countSql) throws SQLException {
final List<T> list = new ArrayList(); final List<T> list = new ArrayList();
if (mysqlOrPgsql) { //sql可以带limit、offset if (mysqlOrPgsql) { //sql可以带limit、offset
PreparedStatement prestmt = conn.prepareQueryStatement(listSql); ResultSet set;
ResultSet set = prestmt.executeQuery(); PreparedStatement prestmt;
final DataResultSet rr = createDataResultSet(info, set); long total = -1;
while (set.next()) {
list.add(getEntityValue(info, sels, rr));
}
set.close();
conn.offerQueryStatement(prestmt);
long total = list.size();
if (needTotal) { if (needTotal) {
prestmt = conn.prepareQueryStatement(countSql); prestmt = conn.prepareQueryStatement(countSql);
set = prestmt.executeQuery(); set = prestmt.executeQuery();
@@ -2347,6 +2341,19 @@ public class DataJdbcSource extends AbstractDataSqlSource {
set.close(); set.close();
conn.offerQueryStatement(prestmt); 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); slowLog(s, listSql);
return new Sheet<>(total, list); return new Sheet<>(total, list);
} else { } else {
@@ -2548,10 +2555,10 @@ public class DataJdbcSource extends AbstractDataSqlSource {
int rs; int rs;
if (sinfo.isEmptyNamed()) { if (sinfo.isEmptyNamed()) {
final Statement stmt = conn.createUpdateStatement(); final Statement stmt = conn.createUpdateStatement();
rs = stmt.executeUpdate(sinfo.nativeSql); rs = stmt.executeUpdate(sinfo.getNativeSql());
conn.offerUpdateStatement(stmt); conn.offerUpdateStatement(stmt);
} else { } else {
final PreparedStatement prestmt = conn.prepareQueryStatement(sinfo.nativeSql); final PreparedStatement prestmt = conn.prepareQueryStatement(sinfo.getNativeSql());
Map<String, Object> paramValues = sinfo.getParamValues(); Map<String, Object> paramValues = sinfo.getParamValues();
int index = 0; int index = 0;
for (String n : sinfo.getParamNames()) { for (String n : sinfo.getParamNames()) {
@@ -2622,7 +2629,7 @@ public class DataJdbcSource extends AbstractDataSqlSource {
final SourceConnection conn = readPool.pollConnection(); final SourceConnection conn = readPool.pollConnection();
try { try {
if (logger.isLoggable(Level.FINEST)) { if (logger.isLoggable(Level.FINEST)) {
logger.finest("executeQuery sql=" + sinfo.nativeSql); logger.finest("executeQuery sql=" + sinfo.getNativeSql());
} }
V rs; V rs;
if (sinfo.isEmptyNamed()) { if (sinfo.isEmptyNamed()) {
@@ -2630,12 +2637,12 @@ public class DataJdbcSource extends AbstractDataSqlSource {
if (consumer != null) { if (consumer != null) {
consumer.accept(conn, stmt); consumer.accept(conn, stmt);
} }
ResultSet set = stmt.executeQuery(sql); ResultSet set = stmt.executeQuery(sinfo.getNativeSql());
rs = handler.apply(createDataResultSet(null, set)); rs = handler.apply(createDataResultSet(null, set));
set.close(); set.close();
conn.offerQueryStatement(stmt); conn.offerQueryStatement(stmt);
} else { } else {
final PreparedStatement prestmt = conn.prepareQueryStatement(sinfo.nativeSql); final PreparedStatement prestmt = conn.prepareQueryStatement(sinfo.getNativeSql());
Map<String, Object> paramValues = sinfo.getParamValues(); Map<String, Object> paramValues = sinfo.getParamValues();
int index = 0; int index = 0;
for (String n : sinfo.getParamNames()) { for (String n : sinfo.getParamNames()) {
@@ -2644,12 +2651,12 @@ public class DataJdbcSource extends AbstractDataSqlSource {
if (consumer != null) { if (consumer != null) {
consumer.accept(conn, prestmt); consumer.accept(conn, prestmt);
} }
ResultSet set = prestmt.executeQuery(sql); ResultSet set = prestmt.executeQuery();
rs = handler.apply(createDataResultSet(null, set)); rs = handler.apply(createDataResultSet(null, set));
set.close(); set.close();
conn.offerQueryStatement(prestmt); conn.offerQueryStatement(prestmt);
} }
slowLog(s, sql); slowLog(s, sinfo.getNativeSql());
return rs; return rs;
} catch (Exception ex) { } catch (Exception ex) {
throw new SourceException(ex); throw new SourceException(ex);
@@ -2660,6 +2667,77 @@ public class DataJdbcSource extends AbstractDataSqlSource {
} }
} }
public <V> Sheet<V> nativeQuerySheet(Class<V> type, String sql, Flipper flipper, Map<String, Object> 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<V> 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<String, Object> 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<String, Object> 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 @Override
public <V> CompletableFuture<V> nativeQueryAsync(String sql, BiConsumer<Object, Object> consumer, Function<DataResultSet, V> handler, Map<String, Object> params) { public <V> CompletableFuture<V> nativeQueryAsync(String sql, BiConsumer<Object, Object> consumer, Function<DataResultSet, V> handler, Map<String, Object> params) {
return supplyAsync(() -> nativeQuery(sql, consumer, handler, params)); return supplyAsync(() -> nativeQuery(sql, consumer, handler, params));
@@ -2685,6 +2763,11 @@ public class DataJdbcSource extends AbstractDataSqlSource {
return supplyAsync(() -> nativeUpdates(sqls)); return supplyAsync(() -> nativeUpdates(sqls));
} }
@Override
public <V> CompletableFuture<Sheet<V>> nativeQuerySheetAsync(Class<V> type, String sql, Flipper flipper, Map<String, Object> params) {
return supplyAsync(() -> nativeQuerySheet(type, sql, flipper, params));
}
@Deprecated @Deprecated
public int directExecute(String sql) { public int directExecute(String sql) {
return nativeUpdate(sql); return nativeUpdate(sql);

View File

@@ -20,13 +20,16 @@ import org.redkale.convert.json.JsonConvert;
*/ */
public interface DataNativeSqlParser { public interface DataNativeSqlParser {
NativeSqlStatement parse(Function<Integer, String> signFunc, String nativeSql, Map<String, Object> params); NativeSqlStatement parse(Function<Integer, String> signFunc, String dbtype, String nativeSql, Map<String, Object> params);
public static class NativeSqlStatement { public static class NativeSqlStatement {
//根据参数值集合重新生成的带?参数可执行的sql //根据参数值集合重新生成的带?参数可执行的sql
protected String nativeSql; protected String nativeSql;
//根据参数值集合重新生成的带?参数可执行的计算总数sql,用于返回Sheet对象
protected String nativeCountSql;
//是否包含InExpression参数名 //是否包含InExpression参数名
protected boolean existInNamed; protected boolean existInNamed;
@@ -54,6 +57,14 @@ public interface DataNativeSqlParser {
this.nativeSql = nativeSql; this.nativeSql = nativeSql;
} }
public String getNativeCountSql() {
return nativeCountSql;
}
public void setNativeCountSql(String nativeCountSql) {
this.nativeCountSql = nativeCountSql;
}
public boolean isExistInNamed() { public boolean isExistInNamed() {
return existInNamed; return existInNamed;
} }

View File

@@ -8,7 +8,7 @@ import java.util.*;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.function.*; import java.util.function.*;
import static org.redkale.source.DataResultSet.formatColumnValue; 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 <V> CompletableFuture<V> nativeQueryAsync(String sql, BiConsumer<Object, Object> consumer, Function<DataResultSet, V> handler, Map<String, Object> params); public <V> CompletableFuture<V> nativeQueryAsync(String sql, BiConsumer<Object, Object> consumer, Function<DataResultSet, V> handler, Map<String, Object> params);
public <V> Sheet<V> nativeQuerySheet(Class<V> type, String sql, Flipper flipper, Map<String, Object> params);
public <V> CompletableFuture<Sheet<V>> nativeQuerySheetAsync(Class<V> type, String sql, Flipper flipper, Map<String, Object> params);
//----------------------------- 无参数 ----------------------------- //----------------------------- 无参数 -----------------------------
default <V> V nativeQuery(String sql, Function<DataResultSet, V> handler) { default <V> V nativeQuery(String sql, Function<DataResultSet, V> handler) {
return nativeQuery(sql, null, handler); return nativeQuery(sql, null, handler);
@@ -138,57 +142,27 @@ public interface DataSqlSource extends DataSource {
} }
default <V> V nativeQueryOne(Class<V> type, String sql) { default <V> V nativeQueryOne(Class<V> type, String sql) {
return nativeQuery(sql, rset -> { return nativeQuery(sql, rset -> EntityBuilder.getOneValue(type, 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);
});
} }
default <V> CompletableFuture<V> nativeQueryOneAsync(Class<V> type, String sql) { default <V> CompletableFuture<V> nativeQueryOneAsync(Class<V> type, String sql) {
return nativeQueryAsync(sql, rset -> { return nativeQueryAsync(sql, rset -> EntityBuilder.getOneValue(type, 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);
});
} }
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 -> EntityBuilder.getListValue(type, rset));
if (type == byte[].class || type == String.class || type.isPrimitive() || Number.class.isAssignableFrom(type)
|| (!Map.class.isAssignableFrom(type) && type.getName().startsWith("java."))) {
List<V> 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);
});
} }
default <V> CompletableFuture<List<V>> nativeQueryListAsync(Class<V> type, String sql) { default <V> CompletableFuture<List<V>> nativeQueryListAsync(Class<V> type, String sql) {
return nativeQueryAsync(sql, rset -> { return nativeQueryAsync(sql, rset -> EntityBuilder.getListValue(type, rset));
if (type == byte[].class || type == String.class || type.isPrimitive() || Number.class.isAssignableFrom(type)
|| (!Map.class.isAssignableFrom(type) && type.getName().startsWith("java."))) {
List<V> list = new ArrayList<>();
while (rset.next()) {
list.add(rset.wasNull() ? null : (V) formatColumnValue(type, rset.getObject(1)));
} }
return list;
default <V> Sheet<V> nativeQuerySheet(Class<V> type, String sql, Flipper flipper) {
return nativeQuerySheet(type, sql, flipper, Collections.emptyMap());
} }
return EntityBuilder.load(type).getObjectList(rset);
}); default <V> CompletableFuture<Sheet<V>> nativeQuerySheetAsync(Class<V> type, String sql, Flipper flipper) {
return nativeQuerySheetAsync(type, sql, flipper, Collections.emptyMap());
} }
default <K, V> Map<K, V> nativeQueryMap(Class<K> keyType, Class<V> valType, String sql) { default <K, V> Map<K, V> nativeQueryMap(Class<K> keyType, Class<V> valType, String sql) {
@@ -390,4 +364,13 @@ public interface DataSqlSource extends DataSource {
default CompletableFuture<Map<Integer, String>> nativeQueryIntStrMapAsync(String sql, Serializable bean) { default CompletableFuture<Map<Integer, String>> nativeQueryIntStrMapAsync(String sql, Serializable bean) {
return nativeQueryMapAsync(Integer.class, String.class, sql, (Map<String, Object>) Copier.copyToMap(bean, Copier.OPTION_SKIP_NULL_VALUE)); return nativeQueryMapAsync(Integer.class, String.class, sql, (Map<String, Object>) Copier.copyToMap(bean, Copier.OPTION_SKIP_NULL_VALUE));
} }
default <V> Sheet<V> nativeQuerySheet(Class<V> type, String sql, Flipper flipper, Serializable bean) {
return nativeQuerySheet(type, sql, flipper, (Map<String, Object>) Copier.copyToMap(bean, Copier.OPTION_SKIP_NULL_VALUE));
}
default <V> CompletableFuture<Sheet<V>> nativeQuerySheetAsync(Class<V> type, String sql, Flipper flipper, Serializable bean) {
return nativeQuerySheetAsync(type, sql, flipper, (Map<String, Object>) Copier.copyToMap(bean, Copier.OPTION_SKIP_NULL_VALUE));
}
} }

View File

@@ -183,6 +183,29 @@ public class EntityBuilder<T> {
unconstructorAttributes, attributeMap, queryAttrs.toArray(new Attribute[queryAttrs.size()])); unconstructorAttributes, attributeMap, queryAttrs.toArray(new Attribute[queryAttrs.size()]));
} }
public static <T> List<T> getListValue(Class<T> 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<T> 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> T getOneValue(Class<T> 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<T> getObjectList(final DataResultSet rset) { public List<T> getObjectList(final DataResultSet rset) {
List<T> list = new ArrayList<>(); List<T> list = new ArrayList<>();
List<String> sqlColumns = rset.getColumnLabels(); List<String> sqlColumns = rset.getColumnLabels();