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()); + } }