增加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) {
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 <V> Sheet<V> nativeQuerySheet(Class<V> type, String sql, Flipper flipper, Map<String, Object> params) {
return nativeQuerySheetAsync(type, sql, flipper, params).join();
}
@Override
public int nativeUpdate(String sql, Map<String, Object> params) {
return nativeUpdateAsync(sql, params).join();

View File

@@ -2328,16 +2328,10 @@ public class DataJdbcSource extends AbstractDataSqlSource {
private <T> Sheet<T> executeQuerySheet(EntityInfo<T> info, boolean needTotal, Flipper flipper, SelectColumn sels,
long s, SourceConnection conn, boolean mysqlOrPgsql, String listSql, String countSql) throws SQLException {
final List<T> 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<String, Object> 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<String, Object> 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 <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
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));
@@ -2685,6 +2763,11 @@ public class DataJdbcSource extends AbstractDataSqlSource {
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
public int directExecute(String sql) {
return nativeUpdate(sql);

View File

@@ -20,13 +20,16 @@ import org.redkale.convert.json.JsonConvert;
*/
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 {
//根据参数值集合重新生成的带?参数可执行的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;
}

View File

@@ -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 <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) {
return nativeQuery(sql, null, handler);
@@ -138,57 +142,27 @@ public interface DataSqlSource extends DataSource {
}
default <V> V nativeQueryOne(Class<V> 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 <V> CompletableFuture<V> nativeQueryOneAsync(Class<V> 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 <V> List<V> nativeQueryList(Class<V> 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<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);
});
return nativeQuery(sql, rset -> EntityBuilder.getListValue(type, rset));
}
default <V> CompletableFuture<List<V>> nativeQueryListAsync(Class<V> 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<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);
});
return nativeQueryAsync(sql, rset -> EntityBuilder.getListValue(type, rset));
}
default <V> Sheet<V> nativeQuerySheet(Class<V> type, String sql, Flipper flipper) {
return nativeQuerySheet(type, sql, flipper, Collections.emptyMap());
}
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) {
@@ -390,4 +364,13 @@ public interface DataSqlSource extends DataSource {
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));
}
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()]));
}
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) {
List<T> list = new ArrayList<>();
List<String> sqlColumns = rset.getColumnLabels();