diff --git a/CHANGELOG.md b/CHANGELOG.md
index b6e2f24df..b1a2644c7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -33,6 +33,7 @@
* 【core 】 NumberUtil增加isOdd、isEven方法(pr#474@Gitee)
* 【http 】 增加HttpGlobalConfig.setBoundary,删除MultipartBody.BOUNDARY和getContentType(issue#I4KSLY@Gitee)
* 【core 】 DateTime增加setMinimalDaysInFirstWeek(issue#1988@Github)
+* 【db 】 Db增加query重载,可支持自定义PreparedStatement,从而支持游标(issue#I4JXWN@Gitee)
*
### 🐞Bug修复
* 【core 】 修复FileResource构造fileName参数无效问题(issue#1942@Github)
diff --git a/hutool-db/src/main/java/cn/hutool/db/AbstractDb.java b/hutool-db/src/main/java/cn/hutool/db/AbstractDb.java
index 0c40d4de2..c18399029 100644
--- a/hutool-db/src/main/java/cn/hutool/db/AbstractDb.java
+++ b/hutool-db/src/main/java/cn/hutool/db/AbstractDb.java
@@ -1,6 +1,7 @@
package cn.hutool.db;
import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.lang.func.Func1;
import cn.hutool.db.dialect.Dialect;
import cn.hutool.db.handler.BeanListHandler;
import cn.hutool.db.handler.EntityHandler;
@@ -20,6 +21,7 @@ import cn.hutool.db.sql.Wrapper;
import javax.sql.DataSource;
import java.io.Serializable;
import java.sql.Connection;
+import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Collection;
import java.util.List;
@@ -194,6 +196,27 @@ public abstract class AbstractDb implements Serializable {
}
}
+ /**
+ * 执行自定义的{@link PreparedStatement},结果使用{@link RsHandler}处理
+ * 此方法主要用于自定义场景,如游标查询等
+ *
+ * @param 结果集需要处理的对象类型
+ * @param statementFunc 自定义{@link PreparedStatement}创建函数
+ * @param rsh 结果集处理对象
+ * @return 结果对象
+ * @throws SQLException SQL执行异常
+ * @since 5.7.17
+ */
+ public T query(Func1 statementFunc, RsHandler rsh) throws SQLException {
+ Connection conn = null;
+ try {
+ conn = this.getConnection();
+ return SqlExecutor.query(conn, statementFunc, rsh);
+ } finally {
+ this.closeConnection(conn);
+ }
+ }
+
/**
* 执行非查询语句
* 语句包括 插入、更新、删除
diff --git a/hutool-db/src/main/java/cn/hutool/db/sql/SqlExecutor.java b/hutool-db/src/main/java/cn/hutool/db/sql/SqlExecutor.java
index e3aa4439b..eb19816dd 100644
--- a/hutool-db/src/main/java/cn/hutool/db/sql/SqlExecutor.java
+++ b/hutool-db/src/main/java/cn/hutool/db/sql/SqlExecutor.java
@@ -1,6 +1,7 @@
package cn.hutool.db.sql;
import cn.hutool.core.collection.ArrayIter;
+import cn.hutool.core.lang.func.Func1;
import cn.hutool.db.DbUtil;
import cn.hutool.db.StatementUtil;
import cn.hutool.db.handler.RsHandler;
@@ -239,6 +240,22 @@ public class SqlExecutor {
return query(conn, namedSql.getSql(), rsh, namedSql.getParams());
}
+ /**
+ * 执行查询语句
+ * 此方法不会关闭Connection
+ *
+ * @param 处理结果类型
+ * @param conn 数据库连接对象
+ * @param sqlBuilder SQL构建器,包含参数
+ * @param rsh 结果集处理对象
+ * @return 结果对象
+ * @throws SQLException SQL执行异常
+ * @since 5.5.3
+ */
+ public static T query(Connection conn, SqlBuilder sqlBuilder, RsHandler rsh) throws SQLException {
+ return query(conn, sqlBuilder.build(), rsh, sqlBuilder.getParamValueArray());
+ }
+
/**
* 执行查询语句
* 此方法不会关闭Connection
@@ -262,19 +279,30 @@ public class SqlExecutor {
}
/**
- * 执行查询语句
- * 此方法不会关闭Connection
+ * 执行自定义的{@link PreparedStatement},结果使用{@link RsHandler}处理
+ * 此方法主要用于自定义场景,如游标查询等
*
* @param 处理结果类型
* @param conn 数据库连接对象
- * @param sqlBuilder SQL构建器,包含参数
- * @param rsh 结果集处理对象
- * @return 结果对象
+ * @param statementFunc 自定义{@link PreparedStatement}创建函数
+ * @param rsh 自定义结果集处理
+ * @return 结果
* @throws SQLException SQL执行异常
- * @since 5.5.3
+ * @since 5.7.17
*/
- public static T query(Connection conn, SqlBuilder sqlBuilder, RsHandler rsh) throws SQLException {
- return query(conn, sqlBuilder.build(), rsh, sqlBuilder.getParamValueArray());
+ public static T query(Connection conn, Func1 statementFunc, RsHandler rsh) throws SQLException {
+ PreparedStatement ps = null;
+ try {
+ ps = statementFunc.call(conn);
+ return executeQuery(ps, rsh);
+ } catch (Exception e) {
+ if(e instanceof SQLException){
+ throw (SQLException) e;
+ }
+ throw new RuntimeException(e);
+ } finally {
+ DbUtil.close(ps);
+ }
}
// -------------------------------------------------------------------------------------- Execute With PreparedStatement
diff --git a/hutool-db/src/test/java/cn/hutool/db/DbTest.java b/hutool-db/src/test/java/cn/hutool/db/DbTest.java
index 7ab8db26f..1002b602e 100644
--- a/hutool-db/src/test/java/cn/hutool/db/DbTest.java
+++ b/hutool-db/src/test/java/cn/hutool/db/DbTest.java
@@ -1,11 +1,14 @@
package cn.hutool.db;
+import cn.hutool.db.handler.EntityListHandler;
import cn.hutool.db.sql.Condition;
import cn.hutool.log.StaticLog;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
@@ -109,4 +112,18 @@ public class DbTest {
db.del("user", "name", "unitTestUser2");
});
}
+
+ @Test
+ @Ignore
+ public void queryFetchTest() throws SQLException {
+ // https://gitee.com/dromara/hutool/issues/I4JXWN
+ Db.use().query((conn->{
+ PreparedStatement ps = conn.prepareStatement("select * from table",
+ ResultSet.TYPE_FORWARD_ONLY,
+ ResultSet.CONCUR_READ_ONLY);
+ ps.setFetchSize(Integer.MIN_VALUE);
+ ps.setFetchDirection(ResultSet.FETCH_FORWARD);
+ return ps;
+ }), new EntityListHandler());
+ }
}