diff --git a/src/main/java/xyz/zhouxy/jdbc/JdbcOperationSupport.java b/src/main/java/xyz/zhouxy/jdbc/JdbcOperationSupport.java
new file mode 100644
index 0000000..b1ae1bd
--- /dev/null
+++ b/src/main/java/xyz/zhouxy/jdbc/JdbcOperationSupport.java
@@ -0,0 +1,471 @@
+/*
+ * Copyright 2024 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package xyz.zhouxy.jdbc;
+
+import java.math.BigDecimal;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import java.util.OptionalDouble;
+import java.util.OptionalInt;
+import java.util.OptionalLong;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import com.google.common.collect.Lists;
+
+import xyz.zhouxy.plusone.commons.collection.CollectionTools;
+import xyz.zhouxy.plusone.commons.util.AssertTools;
+import xyz.zhouxy.plusone.commons.util.OptionalTools;
+
+/**
+ * JdbcOperationSupport
+ *
+ *
+ * 提供静态方法,封装 JDBC 基础操作
+ *
+ *
+ * @author ZhouXY
+ * @since 1.0.0
+ */
+class JdbcOperationSupport {
+
+ // #region - query
+
+ /**
+ * 执行查询,并按照自定义处理逻辑对结果进行处理,将结果转换为指定类型并返回
+ *
+ * @param conn 数据库连接
+ * @param sql SQL
+ * @param params 参数
+ * @param resultHandler 结果处理器,用于处理 {@link ResultSet}
+ */
+ static T query(Connection conn, String sql, Object[] params, ResultHandler resultHandler)
+ throws SQLException {
+ assertConnectionNotNull(conn);
+ assertSqlNotNull(sql);
+ assertResultHandlerNotNull(resultHandler);
+ return queryInternal(conn, sql, params, resultHandler);
+ }
+
+ // #endregion
+
+ // #region - queryList
+
+ /**
+ * 执行查询,将查询结果的每一行数据按照指定逻辑进行处理,返回结果列表
+ *
+ * @param conn 数据库连接
+ * @param sql SQL
+ * @param params 参数
+ * @param rowMapper {@link ResultSet} 中每一行的数据的处理逻辑
+ */
+ static List queryList(Connection conn, String sql, Object[] params, RowMapper rowMapper)
+ throws SQLException {
+ assertConnectionNotNull(conn);
+ assertSqlNotNull(sql);
+ assertRowMapperNotNull(rowMapper);
+ return queryListInternal(conn, sql, params, rowMapper);
+ }
+
+ /**
+ * 执行查询,返回结果映射为指定的类型。当结果为单列时使用
+ *
+ * @param conn 数据库连接
+ * @param sql SQL
+ * @param params 参数
+ * @param clazz 将结果映射为指定的类型
+ */
+ static List queryList(Connection conn, String sql, Object[] params, Class clazz)
+ throws SQLException {
+ assertConnectionNotNull(conn);
+ assertSqlNotNull(sql);
+ assertClazzNotNull(clazz);
+ return queryListInternal(conn, sql, params, (rs, rowNumber) -> rs.getObject(1, clazz));
+ }
+
+ // #endregion
+
+ // #region - queryFirst
+
+ /**
+ * 执行查询,将查询结果的第一行数据按照指定逻辑进行处理,返回 {@link Optional}
+ *
+ * @param conn 数据库连接
+ * @param sql SQL
+ * @param params 参数
+ * @param rowMapper {@link ResultSet} 中每一行的数据的处理逻辑
+ */
+ static Optional queryFirst(Connection conn, String sql, Object[] params, RowMapper rowMapper)
+ throws SQLException {
+ assertConnectionNotNull(conn);
+ assertSqlNotNull(sql);
+ assertRowMapperNotNull(rowMapper);
+ return queryFirstInternal(conn, sql, params, rowMapper);
+ }
+
+ /**
+ * 查询第一行第一列,并转换为指定类型
+ *
+ * @param 目标类型
+ * @param sql SQL
+ * @param params 参数
+ * @param clazz 目标类型
+ */
+ static Optional queryFirst(Connection conn, String sql, Object[] params, Class clazz)
+ throws SQLException {
+ assertConnectionNotNull(conn);
+ assertSqlNotNull(sql);
+ assertClazzNotNull(clazz);
+ return queryFirstInternal(conn, sql, params, (rs, rowNumber) -> rs.getObject(1, clazz));
+ }
+
+ /**
+ * 查询第一行第一列,并转换为字符串
+ *
+ * @param conn 数据库连接
+ * @param sql SQL
+ * @param params 参数
+ */
+ static Optional queryFirstString(Connection conn, String sql, Object[] params)
+ throws SQLException {
+ return queryFirst(conn, sql, params, (rs, rowNumber) -> rs.getString(1));
+ }
+
+ /**
+ * 查询第一行第一列,并转换为整数值
+ *
+ * @param conn 数据库连接
+ * @param sql SQL
+ * @param params 参数
+ */
+ static OptionalInt queryFirstInt(Connection conn, String sql, Object[] params)
+ throws SQLException {
+ Optional result = queryFirst(conn, sql, params, (rs, rowNumber) -> rs.getInt(1));
+ return OptionalTools.toOptionalInt(result);
+ }
+
+ /**
+ * 查询第一行第一列,并转换为长整型
+ *
+ * @param conn 数据库连接
+ * @param sql SQL
+ * @param params 参数
+ */
+ static OptionalLong queryFirstLong(Connection conn, String sql, Object[] params)
+ throws SQLException {
+ Optional result = queryFirst(conn, sql, params, (rs, rowNumber) -> rs.getLong(1));
+ return OptionalTools.toOptionalLong(result);
+ }
+
+ /**
+ * 查询第一行第一列,并转换为双精度浮点型
+ *
+ * @param conn 数据库连接
+ * @param sql SQL
+ * @param params 参数
+ */
+ static OptionalDouble queryFirstDouble(Connection conn, String sql, Object[] params)
+ throws SQLException {
+ Optional result = queryFirst(conn, sql, params, (rs, rowNumber) -> rs.getDouble(1));
+ return OptionalTools.toOptionalDouble(result);
+ }
+
+ /**
+ * 查询第一行第一列,并转换为 {@link BigDecimal}
+ *
+ * @param conn 数据库连接
+ * @param sql SQL
+ * @param params 参数
+ */
+ static Optional queryFirstBigDecimal(Connection conn, String sql, Object[] params)
+ throws SQLException {
+ return queryFirst(conn, sql, params, (rs, rowNumber) -> rs.getBigDecimal(1));
+ }
+
+ // #endregion
+
+ // #region - update & batchUpdate
+
+ /**
+ * 执行更新操作
+ *
+ * @param conn 数据库连接
+ * @param sql 要执行的 SQL
+ * @param params 参数
+ * @return 更新记录数
+ */
+ static int update(Connection conn, String sql, Object[] params)
+ throws SQLException {
+ assertConnectionNotNull(conn);
+ assertSqlNotNull(sql);
+ try (PreparedStatement stmt = conn.prepareStatement(sql)) {
+ fillStatement(stmt, params);
+ return stmt.executeUpdate();
+ }
+ }
+
+ /**
+ * 执行 SQL 并返回生成的 keys
+ *
+ * @param conn 数据库连接
+ * @param sql 要执行的 SQL
+ * @param params 参数
+ * @param rowMapper 行数据映射逻辑
+ *
+ * @return generated keys
+ * @throws SQLException 执行 SQL 遇到异常情况将抛出
+ */
+ static List update(Connection conn, String sql, Object[] params, RowMapper rowMapper)
+ throws SQLException {
+ assertConnectionNotNull(conn);
+ assertSqlNotNull(sql);
+ assertRowMapperNotNull(rowMapper);
+ final List result = new ArrayList<>();
+ try (PreparedStatement stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) {
+ fillStatement(stmt, params);
+ stmt.executeUpdate();
+ try (ResultSet generatedKeys = stmt.getGeneratedKeys();) {
+ int rowNumber = 0;
+ while (generatedKeys.next()) {
+ T e = rowMapper.mapRow(generatedKeys, rowNumber++);
+ result.add(e);
+ }
+ }
+ return result;
+ }
+ }
+
+ /**
+ * 执行批量更新,批量更新数据,返回每条记录更新的行数
+ *
+ * @param conn 数据库连接
+ * @param sql SQL 语句
+ * @param params 参数列表
+ * @param batchSize 每次批量更新的数据量
+ */
+ static List batchUpdate(Connection conn, String sql, Collection params, int batchSize)
+ throws SQLException {
+ assertConnectionNotNull(conn);
+ assertSqlNotNull(sql);
+
+ if (params == null || params.isEmpty()) {
+ return Collections.emptyList();
+ }
+ int executeCount = params.size() / batchSize;
+ executeCount = (params.size() % batchSize == 0) ? executeCount : (executeCount + 1);
+ List result = Lists.newArrayListWithCapacity(executeCount);
+
+ try (PreparedStatement stmt = conn.prepareStatement(sql)) {
+ int i = 0;
+ for (Object[] ps : params) {
+ i++;
+ fillStatement(stmt, ps);
+ stmt.addBatch();
+ if (i % batchSize == 0 || i >= params.size()) {
+ int[] n = stmt.executeBatch();
+ result.add(n);
+ stmt.clearBatch();
+ }
+ }
+ return result;
+ }
+ }
+
+ /**
+ * 批量更新,返回更新成功的记录行数。发生异常时不中断操作,将异常存入 {@code exceptions} 中
+ *
+ * @param conn 数据库连接
+ * @param sql sql语句
+ * @param params 参数列表
+ * @param batchSize 每次批量更新的数据量
+ * @param exceptions 异常列表,用于记录异常信息
+ */
+ static List batchUpdateAndIgnoreException(Connection conn,
+ String sql, @Nullable Collection params, int batchSize,
+ List exceptions)
+ throws SQLException {
+ assertConnectionNotNull(conn);
+ assertSqlNotNull(sql);
+ AssertTools.checkArgument(CollectionTools.isNotEmpty(exceptions),
+ "The list used to store exceptions should be non-null and empty.");
+ if (params == null || params.isEmpty()) {
+ return Collections.emptyList();
+ }
+ int executeCount = params.size() / batchSize;
+ executeCount = (params.size() % batchSize == 0) ? executeCount : (executeCount + 1);
+ List result = Lists.newArrayListWithCapacity(executeCount);
+
+ try (PreparedStatement stmt = conn.prepareStatement(sql)) {
+ int i = 0;
+ for (Object[] ps : params) {
+ i++;
+ fillStatement(stmt, ps);
+ stmt.addBatch();
+ final int batchIndex = i % batchSize;
+ if (batchIndex == 0 || i >= params.size()) {
+ try {
+ int[] n = stmt.executeBatch();
+ result.add(n);
+ stmt.clearBatch();
+ }
+ catch (Exception e) {
+ int n = (i >= params.size() && batchIndex != 0) ? batchIndex : batchSize;
+ result.add(new int[n]);
+ stmt.clearBatch();
+ // 收集异常信息
+ exceptions.add(e);
+ }
+ }
+ }
+ return result;
+ }
+ }
+
+ // #endregion
+
+ // #region - internal
+
+ /**
+ * 执行查询,将查询结果按照指定逻辑进行处理并返回
+ *
+ * @param conn 数据库连接
+ * @param sql SQL
+ * @param params 参数
+ * @param resultHandler 结果处理器,用于处理 {@link ResultSet}
+ */
+ private static T queryInternal(@Nonnull Connection conn,
+ @Nonnull String sql,
+ @Nullable Object[] params,
+ @Nonnull ResultHandler resultHandler)
+ throws SQLException {
+ try (PreparedStatement stmt = conn.prepareStatement(sql)) {
+ fillStatement(stmt, params);
+ try (ResultSet rs = stmt.executeQuery()) {
+ return resultHandler.handle(rs);
+ }
+ }
+ }
+
+ /**
+ * 执行查询,将查询结果的每一行数据按照指定逻辑进行处理,返回结果列表
+ *
+ * @param conn 数据库连接
+ * @param sql SQL
+ * @param params 参数
+ * @param rowMapper {@link ResultSet} 中每一行的数据的处理逻辑
+ */
+ private static List queryListInternal(@Nonnull Connection conn,
+ @Nonnull String sql,
+ @Nullable Object[] params,
+ @Nonnull RowMapper rowMapper)
+ throws SQLException {
+ return queryInternal(conn, sql, params, rs -> {
+ List result = new ArrayList<>();
+ int rowNumber = 0;
+ while (rs.next()) {
+ T e = rowMapper.mapRow(rs, rowNumber++);
+ result.add(e);
+ }
+ return result;
+ });
+ }
+
+ /**
+ * 执行查询,将查询结果的第一行数据按照指定逻辑进行处理,返回 {@link Optional}
+ *
+ * @param conn 数据库连接
+ * @param sql SQL
+ * @param params 参数
+ * @param rowMapper 行数据映射逻辑
+ */
+ private static Optional queryFirstInternal(@Nonnull Connection conn,
+ @Nonnull String sql,
+ @Nullable Object[] params,
+ @Nonnull RowMapper rowMapper)
+ throws SQLException {
+ return queryInternal(conn, sql, params, rs -> {
+ if (rs.next()) {
+ return Optional.ofNullable(rowMapper.mapRow(rs, 0));
+ }
+ return Optional.empty();
+ });
+ }
+
+ // #endregion
+
+ /**
+ * 填充参数
+ */
+ private static void fillStatement(@Nonnull PreparedStatement stmt, @Nullable Object[] params)
+ throws SQLException {
+ if (params != null && params.length > 0) {
+ Object param;
+ for (int i = 0; i < params.length; i++) {
+ param = params[i];
+ if (param instanceof java.sql.Date) {
+ stmt.setDate(i + 1, (java.sql.Date) param);
+ }
+ else if (param instanceof java.sql.Time) {
+ stmt.setTime(i + 1, (java.sql.Time) param);
+ }
+ else if (param instanceof java.sql.Timestamp) {
+ stmt.setTimestamp(i + 1, (java.sql.Timestamp) param);
+ }
+ else {
+ stmt.setObject(i + 1, param);
+ }
+ }
+ }
+ }
+
+ // #region - 参数校验
+
+ private static void assertConnectionNotNull(Connection conn) {
+ AssertTools.checkArgumentNotNull(conn, "The argument \"conn\" could not be null.");
+ }
+
+ private static void assertSqlNotNull(String sql) {
+ AssertTools.checkArgumentNotNull(sql, "The argument \"sql\" could not be null.");
+ }
+
+ private static void assertRowMapperNotNull(RowMapper> rowMapper) {
+ AssertTools.checkArgumentNotNull(rowMapper, "The argument \"rowMapper\" could not be null.");
+ }
+
+ private static void assertResultHandlerNotNull(ResultHandler> resultHandler) {
+ AssertTools.checkArgumentNotNull(resultHandler, "The argument \"resultHandler\" could not be null.");
+ }
+
+ private static void assertClazzNotNull(Class> clazz) {
+ AssertTools.checkArgumentNotNull(clazz, "The argument \"clazz\" could not be null.");
+ }
+
+ // #endregion
+
+ private JdbcOperationSupport() {
+ throw new IllegalStateException("Utility class");
+ }
+}
diff --git a/src/main/java/xyz/zhouxy/jdbc/JdbcOperations.java b/src/main/java/xyz/zhouxy/jdbc/JdbcOperations.java
new file mode 100644
index 0000000..2cfcd97
--- /dev/null
+++ b/src/main/java/xyz/zhouxy/jdbc/JdbcOperations.java
@@ -0,0 +1,359 @@
+package xyz.zhouxy.jdbc;
+
+import java.math.BigDecimal;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.OptionalDouble;
+import java.util.OptionalInt;
+import java.util.OptionalLong;
+
+import javax.annotation.Nullable;
+
+/**
+ * JdbcOperations
+ *
+ *
+ * 定义 JdbcTemplate 的 API
+ *
+ *
+ * @author ZhouXY
+ * @since 1.0.0
+ */
+interface JdbcOperations {
+
+ // #region - query
+
+ /**
+ * 执行查询,并按照自定义处理逻辑对结果进行处理,将结果转换为指定类型并返回
+ *
+ * @param sql SQL
+ * @param params 参数
+ * @param resultHandler 结果处理器,用于处理 {@link ResultSet}
+ */
+ T query(String sql, Object[] params, ResultHandler resultHandler)
+ throws SQLException;
+
+ /**
+ * 执行查询,并按照自定义处理逻辑对结果进行处理,将结果转换为指定类型并返回
+ *
+ * @param sql SQL
+ * @param resultHandler 结果处理器,用于处理 {@link ResultSet}
+ */
+ T query(String sql, ResultHandler resultHandler)
+ throws SQLException;
+
+ // #endregion
+
+ // #region - queryList
+
+ /**
+ * 执行查询,将查询结果的每一行数据按照指定逻辑进行处理,返回结果列表
+ *
+ * @param sql SQL
+ * @param params 参数
+ * @param rowMapper {@link ResultSet} 中每一行的数据的处理逻辑
+ */
+ List queryList(String sql, Object[] params, RowMapper rowMapper)
+ throws SQLException;
+
+ /**
+ * 执行查询,返回结果映射为指定的类型。当结果为单列时使用
+ *
+ * @param sql SQL
+ * @param params 参数
+ * @param clazz 将结果映射为指定的类型
+ */
+ List queryList(String sql, Object[] params, Class clazz)
+ throws SQLException;
+
+ /**
+ * 执行查询,每一行数据映射为 {@code Map},返回结果列表
+ *
+ * @param sql SQL
+ * @param params 参数列表
+ */
+ List> queryList(String sql, Object[] params)
+ throws SQLException;
+
+ /**
+ * 执行查询,每一行数据映射为 {@link DbRecord},返回结果列表
+ *
+ * @param sql SQL
+ * @param params 参数列表
+ */
+ List queryRecordList(String sql, Object[] params)
+ throws SQLException;
+
+ /**
+ * 执行查询,将查询结果的每一行数据按照指定逻辑进行处理,返回结果列表
+ *
+ * @param sql SQL
+ * @param rowMapper {@link ResultSet} 中每一行的数据的处理逻辑
+ */
+ List queryList(String sql, RowMapper rowMapper)
+ throws SQLException;
+
+ /**
+ * 执行查询,返回结果映射为指定的类型。当结果为单列时使用
+ *
+ * @param sql SQL
+ * @param clazz 将结果映射为指定的类型
+ */
+ List queryList(String sql, Class clazz)
+ throws SQLException;
+
+ /**
+ * 执行查询,每一行数据映射为 {@code Map},返回结果列表
+ *
+ * @param sql SQL
+ */
+ List> queryList(String sql)
+ throws SQLException;
+
+ /**
+ * 执行查询,每一行数据映射为 {@link DbRecord},返回结果列表
+ *
+ * @param sql SQL
+ */
+ List queryRecordList(String sql)
+ throws SQLException;
+
+ // #endregion
+
+ // #region - queryFirst
+
+ /**
+ * 执行查询,将查询结果的第一行数据按照指定逻辑进行处理,返回 {@link Optional}
+ *
+ * @param sql SQL
+ * @param params 参数
+ * @param rowMapper {@link ResultSet} 中每一行的数据的处理逻辑
+ */
+ Optional queryFirst(String sql, Object[] params, RowMapper rowMapper)
+ throws SQLException;
+
+ /**
+ * 查询第一行第一列,并转换为指定类型
+ *
+ * @param 目标类型
+ * @param sql SQL
+ * @param params 参数
+ * @param clazz 目标类型
+ */
+ Optional queryFirst(String sql, Object[] params, Class clazz)
+ throws SQLException;
+
+ /**
+ * 执行查询,将第一行数据转为 Map
+ *
+ * @param sql SQL
+ * @param params 参数
+ */
+ Optional> queryFirst(String sql, Object[] params)
+ throws SQLException;
+
+ /**
+ * 执行查询,将第一行数据转为 DbRecord
+ *
+ * @param sql SQL
+ * @param params 参数
+ */
+ Optional queryFirstRecord(String sql, Object[] params)
+ throws SQLException;
+
+ /**
+ * 查询第一行第一列,并转换为字符串
+ *
+ * @param sql SQL
+ * @param params 参数
+ */
+ Optional queryFirstString(String sql, Object[] params)
+ throws SQLException;
+
+ /**
+ * 查询第一行第一列,并转换为整数值
+ *
+ * @param sql SQL
+ * @param params 参数
+ */
+ OptionalInt queryFirstInt(String sql, Object[] params)
+ throws SQLException;
+
+ /**
+ * 查询第一行第一列,并转换为长整型
+ *
+ * @param sql SQL
+ * @param params 参数
+ */
+ OptionalLong queryFirstLong(String sql, Object[] params)
+ throws SQLException;
+
+ /**
+ * 查询第一行第一列,并转换为双精度浮点型
+ *
+ * @param sql SQL
+ * @param params 参数
+ */
+ OptionalDouble queryFirstDouble(String sql, Object[] params)
+ throws SQLException;
+
+ /**
+ * 查询第一行第一列,并转换为 {@link BigDecimal}
+ *
+ * @param sql SQL
+ * @param params 参数
+ */
+ Optional queryFirstBigDecimal(String sql, Object[] params)
+ throws SQLException;
+
+ /**
+ * 执行查询,将查询结果的第一行数据按照指定逻辑进行处理,返回 {@link Optional}
+ *
+ * @param sql SQL
+ * @param rowMapper {@link ResultSet} 中每一行的数据的处理逻辑
+ */
+ Optional queryFirst(String sql, RowMapper rowMapper)
+ throws SQLException;
+
+ /**
+ * 查询第一行第一列,并转换为指定类型
+ *
+ * @param 目标类型
+ * @param sql SQL
+ * @param clazz 目标类型
+ */
+ Optional queryFirst(String sql, Class clazz)
+ throws SQLException;
+
+ /**
+ * 执行查询,将第一行数据转为 Map
+ *
+ * @param sql SQL
+ */
+ Optional> queryFirst(String sql)
+ throws SQLException;
+
+ /**
+ * 执行查询,将第一行数据转为 DbRecord
+ *
+ * @param sql SQL
+ */
+ Optional queryFirstRecord(String sql)
+ throws SQLException;
+
+ /**
+ * 查询第一行第一列,并转换为字符串
+ *
+ * @param sql SQL
+ */
+ Optional queryFirstString(String sql)
+ throws SQLException;
+
+ /**
+ * 查询第一行第一列,并转换为整数值
+ *
+ * @param sql SQL
+ */
+ OptionalInt queryFirstInt(String sql)
+ throws SQLException;
+
+ /**
+ * 查询第一行第一列,并转换为长整型
+ *
+ * @param sql SQL
+ */
+ OptionalLong queryFirstLong(String sql)
+ throws SQLException;
+
+ /**
+ * 查询第一行第一列,并转换为双精度浮点型
+ *
+ * @param sql SQL
+ */
+ OptionalDouble queryFirstDouble(String sql)
+ throws SQLException;
+
+ /**
+ * 查询第一行第一列,并转换为 {@link BigDecimal}
+ *
+ * @param sql SQL
+ */
+ Optional queryFirstBigDecimal(String sql)
+ throws SQLException;
+
+ // #endregion
+
+ // #region - update & batchUpdate
+
+ /**
+ * 执行更新操作
+ *
+ * @param sql 要执行的 SQL
+ * @param params 参数
+ * @return 更新记录数
+ */
+ int update(String sql, Object[] params)
+ throws SQLException;
+
+ /**
+ * 执行更新操作
+ *
+ * @param sql 要执行的 SQL
+ * @return 更新记录数
+ */
+ int update(String sql)
+ throws SQLException;
+
+ /**
+ * 执行 SQL 并返回生成的 keys
+ *
+ * @param sql 要执行的 SQL
+ * @param params 参数
+ * @param rowMapper 行数据映射逻辑
+ *
+ * @return generated keys
+ * @throws SQLException 执行 SQL 遇到异常情况将抛出
+ */
+ List update(String sql, Object[] params, RowMapper rowMapper)
+ throws SQLException;
+
+ /**
+ * 执行 SQL 并返回生成的 keys
+ *
+ * @param sql 要执行的 SQL
+ * @param rowMapper 行数据映射逻辑
+ *
+ * @return generated keys
+ * @throws SQLException 执行 SQL 遇到异常情况将抛出
+ */
+ List update(String sql, RowMapper rowMapper)
+ throws SQLException;
+
+ /**
+ * 执行批量更新,批量更新数据,返回每条记录更新的行数
+ *
+ * @param sql SQL 语句
+ * @param params 参数列表
+ * @param batchSize 每次批量更新的数据量
+ */
+ List batchUpdate(String sql, @Nullable Collection params, int batchSize)
+ throws SQLException;
+
+ /**
+ * 批量更新,返回更新成功的记录行数。发生异常时不中断操作,将异常存入 {@code exceptions} 中
+ *
+ * @param sql sql语句
+ * @param params 参数列表
+ * @param batchSize 每次批量更新的数据量
+ * @param exceptions 异常列表,用于记录异常信息
+ */
+ List batchUpdateAndIgnoreException(String sql, @Nullable Collection params,
+ int batchSize, List exceptions)
+ throws SQLException;
+
+ // #endregion
+}
diff --git a/src/main/java/xyz/zhouxy/jdbc/SimpleJdbcTemplate.java b/src/main/java/xyz/zhouxy/jdbc/SimpleJdbcTemplate.java
index c7beca8..b8a647b 100644
--- a/src/main/java/xyz/zhouxy/jdbc/SimpleJdbcTemplate.java
+++ b/src/main/java/xyz/zhouxy/jdbc/SimpleJdbcTemplate.java
@@ -18,13 +18,8 @@ package xyz.zhouxy.jdbc;
import java.math.BigDecimal;
import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
import java.sql.SQLException;
-import java.sql.Statement;
-import java.util.ArrayList;
import java.util.Collection;
-import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@@ -36,13 +31,9 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.sql.DataSource;
-import com.google.common.collect.Lists;
-
-import xyz.zhouxy.plusone.commons.collection.CollectionTools;
import xyz.zhouxy.plusone.commons.function.ThrowingConsumer;
import xyz.zhouxy.plusone.commons.function.ThrowingPredicate;
import xyz.zhouxy.plusone.commons.util.AssertTools;
-import xyz.zhouxy.plusone.commons.util.OptionalTools;
/**
* SimpleJdbcTemplate
@@ -54,7 +45,7 @@ import xyz.zhouxy.plusone.commons.util.OptionalTools;
* @author ZhouXY
* @since 1.0.0
*/
-public class SimpleJdbcTemplate {
+public class SimpleJdbcTemplate implements JdbcOperations {
@Nonnull
private final DataSource dataSource;
@@ -66,30 +57,21 @@ public class SimpleJdbcTemplate {
// #region - query
- /**
- * 执行查询,并按照自定义处理逻辑对结果进行处理,将结果转换为指定类型并返回
- *
- * @param sql SQL
- * @param params 参数
- * @param resultHandler 结果处理器,用于处理 {@link ResultSet}
- */
+ /** {@inheritDoc} */
+ @Override
public T query(String sql, Object[] params, ResultHandler resultHandler)
throws SQLException {
try (Connection conn = this.dataSource.getConnection()) {
- return JdbcExecutor.query(conn, sql, params, resultHandler);
+ return JdbcOperationSupport.query(conn, sql, params, resultHandler);
}
}
- /**
- * 执行查询,并按照自定义处理逻辑对结果进行处理,将结果转换为指定类型并返回
- *
- * @param sql SQL
- * @param resultHandler 结果处理器,用于处理 {@link ResultSet}
- */
+ /** {@inheritDoc} */
+ @Override
public T query(String sql, ResultHandler resultHandler)
throws SQLException {
try (Connection conn = this.dataSource.getConnection()) {
- return JdbcExecutor.query(conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY, resultHandler);
+ return JdbcOperationSupport.query(conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY, resultHandler);
}
}
@@ -97,107 +79,75 @@ public class SimpleJdbcTemplate {
// #region - queryList
- /**
- * 执行查询,将查询结果的每一行数据按照指定逻辑进行处理,返回结果列表
- *
- * @param sql SQL
- * @param params 参数
- * @param rowMapper {@link ResultSet} 中每一行的数据的处理逻辑
- */
+ /** {@inheritDoc} */
+ @Override
public List queryList(String sql, Object[] params, RowMapper rowMapper)
throws SQLException {
try (Connection conn = this.dataSource.getConnection()) {
- return JdbcExecutor.queryList(conn, sql, params, rowMapper);
+ return JdbcOperationSupport.queryList(conn, sql, params, rowMapper);
}
}
- /**
- * 执行查询,返回结果映射为指定的类型。当结果为单列时使用
- *
- * @param sql SQL
- * @param params 参数
- * @param clazz 将结果映射为指定的类型
- */
+ /** {@inheritDoc} */
+ @Override
public List queryList(String sql, Object[] params, Class clazz)
throws SQLException {
try (Connection conn = this.dataSource.getConnection()) {
- return JdbcExecutor.queryList(conn, sql, params, clazz);
+ return JdbcOperationSupport.queryList(conn, sql, params, clazz);
}
}
- /**
- * 执行查询,每一行数据映射为 {@code Map},返回结果列表
- *
- * @param sql SQL
- * @param params 参数列表
- */
+ /** {@inheritDoc} */
+ @Override
public List> queryList(String sql, Object[] params)
throws SQLException {
try (Connection conn = this.dataSource.getConnection()) {
- return JdbcExecutor.queryList(conn, sql, params, RowMapper.HASH_MAP_MAPPER);
+ return JdbcOperationSupport.queryList(conn, sql, params, RowMapper.HASH_MAP_MAPPER);
}
}
- /**
- * 执行查询,每一行数据映射为 {@link DbRecord},返回结果列表
- *
- * @param sql SQL
- * @param params 参数列表
- */
+ /** {@inheritDoc} */
+ @Override
public List queryRecordList(String sql, Object[] params)
throws SQLException {
try (Connection conn = this.dataSource.getConnection()) {
- return JdbcExecutor.queryList(conn, sql, params, RowMapper.RECORD_MAPPER);
+ return JdbcOperationSupport.queryList(conn, sql, params, RowMapper.RECORD_MAPPER);
}
}
- /**
- * 执行查询,将查询结果的每一行数据按照指定逻辑进行处理,返回结果列表
- *
- * @param sql SQL
- * @param rowMapper {@link ResultSet} 中每一行的数据的处理逻辑
- */
+ /** {@inheritDoc} */
+ @Override
public List queryList(String sql, RowMapper rowMapper)
throws SQLException {
try (Connection conn = this.dataSource.getConnection()) {
- return JdbcExecutor.queryList(conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY, rowMapper);
+ return JdbcOperationSupport.queryList(conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY, rowMapper);
}
}
- /**
- * 执行查询,返回结果映射为指定的类型。当结果为单列时使用
- *
- * @param sql SQL
- * @param clazz 将结果映射为指定的类型
- */
+ /** {@inheritDoc} */
+ @Override
public List queryList(String sql, Class clazz)
throws SQLException {
try (Connection conn = this.dataSource.getConnection()) {
- return JdbcExecutor.queryList(conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY, clazz);
+ return JdbcOperationSupport.queryList(conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY, clazz);
}
}
- /**
- * 执行查询,每一行数据映射为 {@code Map},返回结果列表
- *
- * @param sql SQL
- */
+ /** {@inheritDoc} */
+ @Override
public List> queryList(String sql)
throws SQLException {
try (Connection conn = this.dataSource.getConnection()) {
- return JdbcExecutor.queryList(conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY, RowMapper.HASH_MAP_MAPPER);
+ return JdbcOperationSupport.queryList(conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY, RowMapper.HASH_MAP_MAPPER);
}
}
- /**
- * 执行查询,每一行数据映射为 {@link DbRecord},返回结果列表
- *
- * @param sql SQL
- */
+ /** {@inheritDoc} */
+ @Override
public List queryRecordList(String sql)
throws SQLException {
try (Connection conn = this.dataSource.getConnection()) {
- return JdbcExecutor.queryList(conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY, RowMapper.RECORD_MAPPER);
+ return JdbcOperationSupport.queryList(conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY, RowMapper.RECORD_MAPPER);
}
}
@@ -205,234 +155,165 @@ public class SimpleJdbcTemplate {
// #region - queryFirst
- /**
- * 执行查询,将查询结果的第一行数据按照指定逻辑进行处理,返回 {@link Optional}
- *
- * @param sql SQL
- * @param params 参数
- * @param rowMapper {@link ResultSet} 中每一行的数据的处理逻辑
- */
+ /** {@inheritDoc} */
+ @Override
public Optional queryFirst(String sql, Object[] params, RowMapper rowMapper)
throws SQLException {
try (Connection conn = this.dataSource.getConnection()) {
- return JdbcExecutor.queryFirst(conn, sql, params, rowMapper);
+ return JdbcOperationSupport.queryFirst(conn, sql, params, rowMapper);
}
}
- /**
- * 查询第一行第一列,并转换为指定类型
- *
- * @param 目标类型
- * @param sql SQL
- * @param params 参数
- * @param clazz 目标类型
- */
+ /** {@inheritDoc} */
+ @Override
public Optional queryFirst(String sql, Object[] params, Class clazz)
throws SQLException {
try (Connection conn = this.dataSource.getConnection()) {
- return JdbcExecutor.queryFirst(conn, sql, params, clazz);
+ return JdbcOperationSupport.queryFirst(conn, sql, params, clazz);
}
}
- /**
- * 执行查询,将第一行数据转为 Map
- *
- * @param sql SQL
- * @param params 参数
- */
+ /** {@inheritDoc} */
+ @Override
public Optional> queryFirst(String sql, Object[] params)
throws SQLException {
try (Connection conn = this.dataSource.getConnection()) {
- return JdbcExecutor.queryFirst(conn, sql, params, RowMapper.HASH_MAP_MAPPER);
+ return JdbcOperationSupport.queryFirst(conn, sql, params, RowMapper.HASH_MAP_MAPPER);
}
}
- /**
- * 执行查询,将第一行数据转为 DbRecord
- *
- * @param sql SQL
- * @param params 参数
- */
+ /** {@inheritDoc} */
+ @Override
public Optional queryFirstRecord(String sql, Object[] params)
throws SQLException {
try (Connection conn = this.dataSource.getConnection()) {
- return JdbcExecutor.queryFirst(conn, sql, params, RowMapper.RECORD_MAPPER);
+ return JdbcOperationSupport.queryFirst(conn, sql, params, RowMapper.RECORD_MAPPER);
}
}
- /**
- * 查询第一行第一列,并转换为字符串
- *
- * @param sql SQL
- * @param params 参数
- */
+ /** {@inheritDoc} */
+ @Override
public Optional queryFirstString(String sql, Object[] params)
throws SQLException {
try (Connection conn = this.dataSource.getConnection()) {
- return JdbcExecutor.queryFirstString(conn, sql, params);
+ return JdbcOperationSupport.queryFirstString(conn, sql, params);
}
}
- /**
- * 查询第一行第一列,并转换为整数值
- *
- * @param sql SQL
- * @param params 参数
- */
+ /** {@inheritDoc} */
+ @Override
public OptionalInt queryFirstInt(String sql, Object[] params)
throws SQLException {
try (Connection conn = this.dataSource.getConnection()) {
- return JdbcExecutor.queryFirstInt(conn, sql, params);
+ return JdbcOperationSupport.queryFirstInt(conn, sql, params);
}
}
- /**
- * 查询第一行第一列,并转换为长整型
- *
- * @param sql SQL
- * @param params 参数
- */
+ /** {@inheritDoc} */
+ @Override
public OptionalLong queryFirstLong(String sql, Object[] params)
throws SQLException {
try (Connection conn = this.dataSource.getConnection()) {
- return JdbcExecutor.queryFirstLong(conn, sql, params);
+ return JdbcOperationSupport.queryFirstLong(conn, sql, params);
}
}
- /**
- * 查询第一行第一列,并转换为双精度浮点型
- *
- * @param sql SQL
- * @param params 参数
- */
+ /** {@inheritDoc} */
+ @Override
public OptionalDouble queryFirstDouble(String sql, Object[] params)
throws SQLException {
try (Connection conn = this.dataSource.getConnection()) {
- return JdbcExecutor.queryFirstDouble(conn, sql, params);
+ return JdbcOperationSupport.queryFirstDouble(conn, sql, params);
}
}
- /**
- * 查询第一行第一列,并转换为 {@link BigDecimal}
- *
- * @param sql SQL
- * @param params 参数
- */
+ /** {@inheritDoc} */
+ @Override
public Optional queryFirstBigDecimal(String sql, Object[] params)
throws SQLException {
try (Connection conn = this.dataSource.getConnection()) {
- return JdbcExecutor.queryFirstBigDecimal(conn, sql, params);
+ return JdbcOperationSupport.queryFirstBigDecimal(conn, sql, params);
}
}
- /**
- * 执行查询,将查询结果的第一行数据按照指定逻辑进行处理,返回 {@link Optional}
- *
- * @param sql SQL
- * @param rowMapper {@link ResultSet} 中每一行的数据的处理逻辑
- */
+ /** {@inheritDoc} */
+ @Override
public Optional queryFirst(String sql, RowMapper rowMapper)
throws SQLException {
try (Connection conn = this.dataSource.getConnection()) {
- return JdbcExecutor.queryFirst(conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY, rowMapper);
+ return JdbcOperationSupport.queryFirst(conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY, rowMapper);
}
}
- /**
- * 查询第一行第一列,并转换为指定类型
- *
- * @param 目标类型
- * @param sql SQL
- * @param clazz 目标类型
- */
+ /** {@inheritDoc} */
+ @Override
public Optional queryFirst(String sql, Class clazz)
throws SQLException {
try (Connection conn = this.dataSource.getConnection()) {
- return JdbcExecutor.queryFirst(conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY, clazz);
+ return JdbcOperationSupport.queryFirst(conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY, clazz);
}
}
- /**
- * 执行查询,将第一行数据转为 Map
- *
- * @param sql SQL
- */
+ /** {@inheritDoc} */
+ @Override
public Optional> queryFirst(String sql)
throws SQLException {
try (Connection conn = this.dataSource.getConnection()) {
- return JdbcExecutor.queryFirst(conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY, RowMapper.HASH_MAP_MAPPER);
+ return JdbcOperationSupport.queryFirst(conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY, RowMapper.HASH_MAP_MAPPER);
}
}
- /**
- * 执行查询,将第一行数据转为 DbRecord
- *
- * @param sql SQL
- */
+ /** {@inheritDoc} */
+ @Override
public Optional queryFirstRecord(String sql)
throws SQLException {
try (Connection conn = this.dataSource.getConnection()) {
- return JdbcExecutor.queryFirst(conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY, RowMapper.RECORD_MAPPER);
+ return JdbcOperationSupport.queryFirst(conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY, RowMapper.RECORD_MAPPER);
}
}
- /**
- * 查询第一行第一列,并转换为字符串
- *
- * @param sql SQL
- */
+ /** {@inheritDoc} */
+ @Override
public Optional queryFirstString(String sql)
throws SQLException {
try (Connection conn = this.dataSource.getConnection()) {
- return JdbcExecutor.queryFirstString(conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY);
+ return JdbcOperationSupport.queryFirstString(conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY);
}
}
- /**
- * 查询第一行第一列,并转换为整数值
- *
- * @param sql SQL
- */
+ /** {@inheritDoc} */
+ @Override
public OptionalInt queryFirstInt(String sql)
throws SQLException {
try (Connection conn = this.dataSource.getConnection()) {
- return JdbcExecutor.queryFirstInt(conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY);
+ return JdbcOperationSupport.queryFirstInt(conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY);
}
}
- /**
- * 查询第一行第一列,并转换为长整型
- *
- * @param sql SQL
- */
+ /** {@inheritDoc} */
+ @Override
public OptionalLong queryFirstLong(String sql)
throws SQLException {
try (Connection conn = this.dataSource.getConnection()) {
- return JdbcExecutor.queryFirstLong(conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY);
+ return JdbcOperationSupport.queryFirstLong(conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY);
}
}
- /**
- * 查询第一行第一列,并转换为双精度浮点型
- *
- * @param sql SQL
- */
+ /** {@inheritDoc} */
+ @Override
public OptionalDouble queryFirstDouble(String sql)
throws SQLException {
try (Connection conn = this.dataSource.getConnection()) {
- return JdbcExecutor.queryFirstDouble(conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY);
+ return JdbcOperationSupport.queryFirstDouble(conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY);
}
}
- /**
- * 查询第一行第一列,并转换为 {@link BigDecimal}
- *
- * @param sql SQL
- */
+ /** {@inheritDoc} */
+ @Override
public Optional queryFirstBigDecimal(String sql)
throws SQLException {
try (Connection conn = this.dataSource.getConnection()) {
- return JdbcExecutor.queryFirstBigDecimal(conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY);
+ return JdbcOperationSupport.queryFirstBigDecimal(conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY);
}
}
@@ -440,93 +321,58 @@ public class SimpleJdbcTemplate {
// #region - update & batchUpdate
- /**
- * 执行更新操作
- *
- * @param sql 要执行的 SQL
- * @param params 参数
- * @return 更新记录数
- */
+ /** {@inheritDoc} */
+ @Override
public int update(String sql, Object[] params)
throws SQLException {
try (Connection conn = this.dataSource.getConnection()) {
- return JdbcExecutor.update(conn, sql, params);
+ return JdbcOperationSupport.update(conn, sql, params);
}
}
- /**
- * 执行更新操作
- *
- * @param sql 要执行的 SQL
- * @return 更新记录数
- */
+ /** {@inheritDoc} */
+ @Override
public int update(String sql)
throws SQLException {
try (Connection conn = this.dataSource.getConnection()) {
- return JdbcExecutor.update(conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY);
+ return JdbcOperationSupport.update(conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY);
}
}
- /**
- * 执行 SQL 并返回生成的 keys
- *
- * @param sql 要执行的 SQL
- * @param params 参数
- * @param rowMapper 行数据映射逻辑
- *
- * @return generated keys
- * @throws SQLException 执行 SQL 遇到异常情况将抛出
- */
+ /** {@inheritDoc} */
+ @Override
public List update(String sql, Object[] params, RowMapper rowMapper)
throws SQLException {
try (Connection conn = this.dataSource.getConnection()) {
- return JdbcExecutor.update(conn, sql, params, rowMapper);
+ return JdbcOperationSupport.update(conn, sql, params, rowMapper);
}
}
- /**
- * 执行 SQL 并返回生成的 keys
- *
- * @param sql 要执行的 SQL
- * @param rowMapper 行数据映射逻辑
- *
- * @return generated keys
- * @throws SQLException 执行 SQL 遇到异常情况将抛出
- */
+ /** {@inheritDoc} */
+ @Override
public List update(String sql, RowMapper rowMapper)
throws SQLException {
try (Connection conn = this.dataSource.getConnection()) {
- return JdbcExecutor.update(conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY, rowMapper);
+ return JdbcOperationSupport.update(conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY, rowMapper);
}
}
- /**
- * 执行批量更新,批量更新数据,返回每条记录更新的行数
- *
- * @param sql SQL 语句
- * @param params 参数列表
- * @param batchSize 每次批量更新的数据量
- */
+ /** {@inheritDoc} */
+ @Override
public List batchUpdate(String sql, @Nullable Collection params, int batchSize)
throws SQLException {
try (Connection conn = this.dataSource.getConnection()) {
- return JdbcExecutor.batchUpdate(conn, sql, params, batchSize);
+ return JdbcOperationSupport.batchUpdate(conn, sql, params, batchSize);
}
}
- /**
- * 批量更新,返回更新成功的记录行数。发生异常时不中断操作,将异常存入 {@code exceptions} 中
- *
- * @param sql sql语句
- * @param params 参数列表
- * @param batchSize 每次批量更新的数据量
- * @param exceptions 异常列表,用于记录异常信息
- */
+ /** {@inheritDoc} */
+ @Override
public List batchUpdateAndIgnoreException(String sql, @Nullable Collection params,
int batchSize, List exceptions)
throws SQLException {
try (Connection conn = this.dataSource.getConnection()) {
- return JdbcExecutor.batchUpdateAndIgnoreException(conn, sql, params, batchSize, exceptions);
+ return JdbcOperationSupport.batchUpdateAndIgnoreException(conn, sql, params, batchSize, exceptions);
}
}
@@ -602,7 +448,7 @@ public class SimpleJdbcTemplate {
// #endregion
- public static final class JdbcExecutor {
+ public static final class JdbcExecutor implements JdbcOperations {
private final Connection conn;
@@ -612,813 +458,259 @@ public class SimpleJdbcTemplate {
// #region - query
- /**
- * 执行查询,并按照自定义处理逻辑对结果进行处理,将结果转换为指定类型并返回
- *
- * @param sql SQL
- * @param params 参数
- * @param resultHandler 结果处理器,用于处理 {@link ResultSet}
- */
+ /** {@inheritDoc} */
+ @Override
public T query(String sql, Object[] params, ResultHandler resultHandler)
throws SQLException {
- return JdbcExecutor.query(this.conn, sql, params, resultHandler);
+ return JdbcOperationSupport.query(this.conn, sql, params, resultHandler);
}
- /**
- * 执行查询,并按照自定义处理逻辑对结果进行处理,将结果转换为指定类型并返回
- *
- * @param sql SQL
- * @param resultHandler 结果处理器,用于处理 {@link ResultSet}
- */
+ /** {@inheritDoc} */
+ @Override
public T query(String sql, ResultHandler resultHandler)
throws SQLException {
- return JdbcExecutor.query(this.conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY, resultHandler);
+ return JdbcOperationSupport.query(this.conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY, resultHandler);
}
// #endregion
// #region - queryList
- /**
- * 执行查询,将查询结果的每一行数据按照指定逻辑进行处理,返回结果列表
- *
- * @param sql SQL
- * @param params 参数
- * @param rowMapper {@link ResultSet} 中每一行的数据的处理逻辑
- */
+ /** {@inheritDoc} */
+ @Override
public List queryList(String sql, Object[] params, RowMapper rowMapper)
throws SQLException {
- return JdbcExecutor.queryList(this.conn, sql, params, rowMapper);
+ return JdbcOperationSupport.queryList(this.conn, sql, params, rowMapper);
}
- /**
- * 执行查询,返回结果映射为指定的类型。当结果为单列时使用
- *
- * @param sql SQL
- * @param params 参数
- * @param clazz 将结果映射为指定的类型
- */
+ /** {@inheritDoc} */
+ @Override
public List queryList(String sql, Object[] params, Class clazz)
throws SQLException {
- return JdbcExecutor.queryList(this.conn, sql, params, clazz);
+ return JdbcOperationSupport.queryList(this.conn, sql, params, clazz);
}
- /**
- * 执行查询,每一行数据映射为 {@code Map},返回结果列表
- *
- * @param sql SQL
- * @param params 参数列表
- */
+ /** {@inheritDoc} */
+ @Override
public List> queryList(String sql, Object[] params)
throws SQLException {
- return JdbcExecutor.queryList(this.conn, sql, params, RowMapper.HASH_MAP_MAPPER);
+ return JdbcOperationSupport.queryList(this.conn, sql, params, RowMapper.HASH_MAP_MAPPER);
}
- /**
- * 执行查询,每一行数据映射为 {@link DbRecord},返回结果列表
- *
- * @param sql SQL
- * @param params 参数列表
- */
+ /** {@inheritDoc} */
+ @Override
public List queryRecordList(String sql, Object[] params)
throws SQLException {
- return JdbcExecutor.queryList(this.conn, sql, params, RowMapper.RECORD_MAPPER);
+ return JdbcOperationSupport.queryList(this.conn, sql, params, RowMapper.RECORD_MAPPER);
}
- /**
- * 执行查询,将查询结果的每一行数据按照指定逻辑进行处理,返回结果列表
- *
- * @param sql SQL
- * @param rowMapper {@link ResultSet} 中每一行的数据的处理逻辑
- */
+ /** {@inheritDoc} */
+ @Override
public List queryList(String sql, RowMapper rowMapper)
throws SQLException {
- return JdbcExecutor.queryList(this.conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY, rowMapper);
+ return JdbcOperationSupport.queryList(this.conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY, rowMapper);
}
- /**
- * 执行查询,返回结果映射为指定的类型。当结果为单列时使用
- *
- * @param sql SQL
- * @param clazz 将结果映射为指定的类型
- */
+ /** {@inheritDoc} */
+ @Override
public List queryList(String sql, Class clazz)
throws SQLException {
- return JdbcExecutor.queryList(this.conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY, clazz);
+ return JdbcOperationSupport.queryList(this.conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY, clazz);
}
- /**
- * 执行查询,每一行数据映射为 {@code Map},返回结果列表
- *
- * @param sql SQL
- */
+ /** {@inheritDoc} */
+ @Override
public List> queryList(String sql)
throws SQLException {
- return JdbcExecutor.queryList(this.conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY, RowMapper.HASH_MAP_MAPPER);
+ return JdbcOperationSupport.queryList(this.conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY, RowMapper.HASH_MAP_MAPPER);
}
- /**
- * 执行查询,每一行数据映射为 {@link DbRecord},返回结果列表
- *
- * @param sql SQL
- */
+ /** {@inheritDoc} */
+ @Override
public List queryRecordList(String sql)
throws SQLException {
- return JdbcExecutor.queryList(this.conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY, RowMapper.RECORD_MAPPER);
+ return JdbcOperationSupport.queryList(this.conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY, RowMapper.RECORD_MAPPER);
}
// #endregion
// #region - queryFirst
- /**
- * 执行查询,将查询结果的第一行数据按照指定逻辑进行处理,返回 {@link Optional}
- *
- * @param sql SQL
- * @param params 参数
- * @param rowMapper {@link ResultSet} 中每一行的数据的处理逻辑
- */
+ /** {@inheritDoc} */
+ @Override
public Optional queryFirst(String sql, Object[] params, RowMapper rowMapper)
throws SQLException {
- return JdbcExecutor.queryFirst(this.conn, sql, params, rowMapper);
+ return JdbcOperationSupport.queryFirst(this.conn, sql, params, rowMapper);
}
- /**
- * 查询第一行第一列,并转换为指定类型
- *
- * @param 目标类型
- * @param sql SQL
- * @param params 参数
- * @param clazz 目标类型
- */
+ /** {@inheritDoc} */
+ @Override
public Optional queryFirst(String sql, Object[] params, Class clazz)
throws SQLException {
- return JdbcExecutor.queryFirst(this.conn, sql, params, clazz);
+ return JdbcOperationSupport.queryFirst(this.conn, sql, params, clazz);
}
- /**
- * 执行查询,将第一行数据转为 Map
- *
- * @param sql SQL
- * @param params 参数
- */
+ /** {@inheritDoc} */
+ @Override
public Optional> queryFirst(String sql, Object[] params)
throws SQLException {
- return JdbcExecutor.queryFirst(this.conn, sql, params, RowMapper.HASH_MAP_MAPPER);
+ return JdbcOperationSupport.queryFirst(this.conn, sql, params, RowMapper.HASH_MAP_MAPPER);
}
- /**
- * 执行查询,将第一行数据转为 DbRecord
- *
- * @param sql SQL
- * @param params 参数
- */
+ /** {@inheritDoc} */
+ @Override
public Optional queryFirstRecord(String sql, Object[] params)
throws SQLException {
- return JdbcExecutor.queryFirst(this.conn, sql, params, RowMapper.RECORD_MAPPER);
+ return JdbcOperationSupport.queryFirst(this.conn, sql, params, RowMapper.RECORD_MAPPER);
}
- /**
- * 查询第一行第一列,并转换为字符串
- *
- * @param sql SQL
- * @param params 参数
- */
+ /** {@inheritDoc} */
+ @Override
public Optional queryFirstString(String sql, Object[] params)
throws SQLException {
- return JdbcExecutor.queryFirstString(this.conn, sql, params);
+ return JdbcOperationSupport.queryFirstString(this.conn, sql, params);
}
- /**
- * 查询第一行第一列,并转换为整数值
- *
- * @param sql SQL
- * @param params 参数
- */
+ /** {@inheritDoc} */
+ @Override
public OptionalInt queryFirstInt(String sql, Object[] params)
throws SQLException {
- return JdbcExecutor.queryFirstInt(this.conn, sql, params);
+ return JdbcOperationSupport.queryFirstInt(this.conn, sql, params);
}
- /**
- * 查询第一行第一列,并转换为长整型
- *
- * @param sql SQL
- * @param params 参数
- */
+ /** {@inheritDoc} */
+ @Override
public OptionalLong queryFirstLong(String sql, Object[] params)
throws SQLException {
- return JdbcExecutor.queryFirstLong(this.conn, sql, params);
+ return JdbcOperationSupport.queryFirstLong(this.conn, sql, params);
}
- /**
- * 查询第一行第一列,并转换为双精度浮点型
- *
- * @param sql SQL
- * @param params 参数
- */
+ /** {@inheritDoc} */
+ @Override
public OptionalDouble queryFirstDouble(String sql, Object[] params)
throws SQLException {
- return JdbcExecutor.queryFirstDouble(this.conn, sql, params);
+ return JdbcOperationSupport.queryFirstDouble(this.conn, sql, params);
}
- /**
- * 查询第一行第一列,并转换为 {@link BigDecimal}
- *
- * @param sql SQL
- * @param params 参数
- */
+ /** {@inheritDoc} */
+ @Override
public Optional queryFirstBigDecimal(String sql, Object[] params)
throws SQLException {
- return JdbcExecutor.queryFirstBigDecimal(this.conn, sql, params);
+ return JdbcOperationSupport.queryFirstBigDecimal(this.conn, sql, params);
}
- /**
- * 执行查询,将查询结果的第一行数据按照指定逻辑进行处理,返回 {@link Optional}
- *
- * @param sql SQL
- * @param rowMapper {@link ResultSet} 中每一行的数据的处理逻辑
- */
+ /** {@inheritDoc} */
+ @Override
public Optional queryFirst(String sql, RowMapper rowMapper)
throws SQLException {
- return JdbcExecutor.queryFirst(this.conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY, rowMapper);
+ return JdbcOperationSupport.queryFirst(this.conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY, rowMapper);
}
- /**
- * 查询第一行第一列,并转换为指定类型
- *
- * @param 目标类型
- * @param sql SQL
- * @param clazz 目标类型
- */
+ /** {@inheritDoc} */
+ @Override
public Optional queryFirst(String sql, Class clazz)
throws SQLException {
- return JdbcExecutor.queryFirst(this.conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY, clazz);
+ return JdbcOperationSupport.queryFirst(this.conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY, clazz);
}
- /**
- * 执行查询,将第一行数据转为 Map
- *
- * @param sql SQL
- */
+ /** {@inheritDoc} */
+ @Override
public Optional> queryFirst(String sql)
throws SQLException {
- return JdbcExecutor.queryFirst(this.conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY, RowMapper.HASH_MAP_MAPPER);
+ return JdbcOperationSupport.queryFirst(this.conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY, RowMapper.HASH_MAP_MAPPER);
}
- /**
- * 执行查询,将第一行数据转为 DbRecord
- *
- * @param sql SQL
- */
+ /** {@inheritDoc} */
+ @Override
public Optional queryFirstRecord(String sql)
throws SQLException {
- return JdbcExecutor.queryFirst(this.conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY, RowMapper.RECORD_MAPPER);
+ return JdbcOperationSupport.queryFirst(this.conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY, RowMapper.RECORD_MAPPER);
}
- /**
- * 查询第一行第一列,并转换为字符串
- *
- * @param sql SQL
- */
+ /** {@inheritDoc} */
+ @Override
public Optional queryFirstString(String sql)
throws SQLException {
- return JdbcExecutor.queryFirstString(this.conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY);
+ return JdbcOperationSupport.queryFirstString(this.conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY);
}
- /**
- * 查询第一行第一列,并转换为整数值
- *
- * @param sql SQL
- */
+ /** {@inheritDoc} */
+ @Override
public OptionalInt queryFirstInt(String sql)
throws SQLException {
- return JdbcExecutor.queryFirstInt(this.conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY);
+ return JdbcOperationSupport.queryFirstInt(this.conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY);
}
- /**
- * 查询第一行第一列,并转换为长整型
- *
- * @param sql SQL
- */
+ /** {@inheritDoc} */
+ @Override
public OptionalLong queryFirstLong(String sql)
throws SQLException {
- return JdbcExecutor.queryFirstLong(this.conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY);
+ return JdbcOperationSupport.queryFirstLong(this.conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY);
}
- /**
- * 查询第一行第一列,并转换为双精度浮点型
- *
- * @param sql SQL
- */
+ /** {@inheritDoc} */
+ @Override
public OptionalDouble queryFirstDouble(String sql)
throws SQLException {
- return JdbcExecutor.queryFirstDouble(this.conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY);
+ return JdbcOperationSupport.queryFirstDouble(this.conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY);
}
- /**
- * 查询第一行第一列,并转换为 {@link BigDecimal}
- *
- * @param sql SQL
- */
+ /** {@inheritDoc} */
+ @Override
public Optional queryFirstBigDecimal(String sql)
throws SQLException {
- return JdbcExecutor.queryFirstBigDecimal(this.conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY);
+ return JdbcOperationSupport.queryFirstBigDecimal(this.conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY);
}
// #endregion
// #region - update & batchUpdate
- /**
- * 执行更新操作
- *
- * @param sql 要执行的 SQL
- * @param params 参数
- * @return 更新记录数
- */
+ /** {@inheritDoc} */
+ @Override
public int update(String sql, Object[] params)
throws SQLException {
- return JdbcExecutor.update(this.conn, sql, params);
+ return JdbcOperationSupport.update(this.conn, sql, params);
}
- /**
- * 执行更新操作
- *
- * @param sql 要执行的 SQL
- * @return 更新记录数
- */
+ /** {@inheritDoc} */
+ @Override
public int update(String sql)
throws SQLException {
- return JdbcExecutor.update(this.conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY);
+ return JdbcOperationSupport.update(this.conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY);
}
- /**
- * 执行 SQL 并返回生成的 keys
- *
- * @param sql 要执行的 SQL
- * @param params 参数
- * @param rowMapper 行数据映射逻辑
- *
- * @return generated keys
- * @throws SQLException 执行 SQL 遇到异常情况将抛出
- */
+ /** {@inheritDoc} */
+ @Override
public List update(String sql, Object[] params, RowMapper rowMapper)
throws SQLException {
- return JdbcExecutor.update(this.conn, sql, params, rowMapper);
+ return JdbcOperationSupport.update(this.conn, sql, params, rowMapper);
}
- /**
- * 执行 SQL 并返回生成的 keys
- *
- * @param sql 要执行的 SQL
- * @param rowMapper 行数据映射逻辑
- *
- * @return generated keys
- * @throws SQLException 执行 SQL 遇到异常情况将抛出
- */
+ /** {@inheritDoc} */
+ @Override
public List update(String sql, RowMapper rowMapper)
throws SQLException {
- return JdbcExecutor.update(this.conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY, rowMapper);
+ return JdbcOperationSupport.update(this.conn, sql, ParamBuilder.EMPTY_OBJECT_ARRAY, rowMapper);
}
- /**
- * 执行批量更新,批量更新数据,返回每条记录更新的行数
- *
- * @param sql SQL 语句
- * @param params 参数列表
- * @param batchSize 每次批量更新的数据量
- */
+ /** {@inheritDoc} */
+ @Override
public List batchUpdate(String sql, @Nullable Collection params, int batchSize)
throws SQLException {
- return JdbcExecutor.batchUpdate(this.conn, sql, params, batchSize);
+ return JdbcOperationSupport.batchUpdate(this.conn, sql, params, batchSize);
}
- /**
- * 批量更新,返回更新成功的记录行数。发生异常时不中断操作,将异常存入 {@code exceptions} 中
- *
- * @param sql sql语句
- * @param params 参数列表
- * @param batchSize 每次批量更新的数据量
- * @param exceptions 异常列表,用于记录异常信息
- */
+ /** {@inheritDoc} */
+ @Override
public List batchUpdateAndIgnoreException(String sql, @Nullable Collection params,
int batchSize, List exceptions)
throws SQLException {
- return JdbcExecutor.batchUpdateAndIgnoreException(this.conn, sql, params, batchSize, exceptions);
+ return JdbcOperationSupport.batchUpdateAndIgnoreException(this.conn, sql, params, batchSize, exceptions);
}
// #endregion
- // #region - internal
-
- /**
- * 执行查询,将查询结果按照指定逻辑进行处理并返回
- *
- * @param conn 数据库连接
- * @param sql SQL
- * @param params 参数
- * @param resultHandler 结果处理器,用于处理 {@link ResultSet}
- */
- private static T queryInternal(@Nonnull Connection conn,
- @Nonnull String sql,
- @Nullable Object[] params,
- @Nonnull ResultHandler resultHandler)
- throws SQLException {
- try (PreparedStatement stmt = conn.prepareStatement(sql)) {
- fillStatement(stmt, params);
- try (ResultSet rs = stmt.executeQuery()) {
- return resultHandler.handle(rs);
- }
- }
- }
-
- /**
- * 执行查询,将查询结果的每一行数据按照指定逻辑进行处理,返回结果列表
- *
- * @param conn 数据库连接
- * @param sql SQL
- * @param params 参数
- * @param rowMapper {@link ResultSet} 中每一行的数据的处理逻辑
- */
- private static List queryListInternal(@Nonnull Connection conn,
- @Nonnull String sql,
- @Nullable Object[] params,
- @Nonnull RowMapper rowMapper)
- throws SQLException {
- return queryInternal(conn, sql, params, rs -> {
- List result = new ArrayList<>();
- int rowNumber = 0;
- while (rs.next()) {
- T e = rowMapper.mapRow(rs, rowNumber++);
- result.add(e);
- }
- return result;
- });
- }
-
- /**
- * 执行查询,将查询结果的第一行数据按照指定逻辑进行处理,返回 {@link Optional}
- *
- * @param conn 数据库连接
- * @param sql SQL
- * @param params 参数
- * @param rowMapper 行数据映射逻辑
- */
- private static Optional queryFirstInternal(@Nonnull Connection conn,
- @Nonnull String sql,
- @Nullable Object[] params,
- @Nonnull RowMapper rowMapper)
- throws SQLException {
- return queryInternal(conn, sql, params, rs -> {
- if (rs.next()) {
- return Optional.ofNullable(rowMapper.mapRow(rs, 0));
- }
- return Optional.empty();
- });
- }
-
- // #endregion
-
- // #region - query
-
- /**
- * 执行查询,并按照自定义处理逻辑对结果进行处理,将结果转换为指定类型并返回
- *
- * @param conn 数据库连接
- * @param sql SQL
- * @param params 参数
- * @param resultHandler 结果处理器,用于处理 {@link ResultSet}
- */
- private static T query(Connection conn, String sql, Object[] params, ResultHandler resultHandler)
- throws SQLException {
- assertConnectionNotNull(conn);
- assertSqlNotNull(sql);
- assertResultHandlerNotNull(resultHandler);
- return queryInternal(conn, sql, params, resultHandler);
- }
-
- // #endregion
-
- // #region - queryList
-
- /**
- * 执行查询,将查询结果的每一行数据按照指定逻辑进行处理,返回结果列表
- *
- * @param conn 数据库连接
- * @param sql SQL
- * @param params 参数
- * @param rowMapper {@link ResultSet} 中每一行的数据的处理逻辑
- */
- private static List queryList(Connection conn, String sql, Object[] params, RowMapper rowMapper)
- throws SQLException {
- assertConnectionNotNull(conn);
- assertSqlNotNull(sql);
- assertRowMapperNotNull(rowMapper);
- return queryListInternal(conn, sql, params, rowMapper);
- }
-
- /**
- * 执行查询,返回结果映射为指定的类型。当结果为单列时使用
- *
- * @param conn 数据库连接
- * @param sql SQL
- * @param params 参数
- * @param clazz 将结果映射为指定的类型
- */
- private static List queryList(Connection conn, String sql, Object[] params, Class clazz)
- throws SQLException {
- assertConnectionNotNull(conn);
- assertSqlNotNull(sql);
- assertClazzNotNull(clazz);
- return queryListInternal(conn, sql, params, (rs, rowNumber) -> rs.getObject(1, clazz));
- }
-
- // #endregion
-
- // #region - queryFirst
-
- /**
- * 执行查询,将查询结果的第一行数据按照指定逻辑进行处理,返回 {@link Optional}
- *
- * @param conn 数据库连接
- * @param sql SQL
- * @param params 参数
- * @param rowMapper {@link ResultSet} 中每一行的数据的处理逻辑
- */
- private static Optional queryFirst(Connection conn, String sql, Object[] params, RowMapper rowMapper)
- throws SQLException {
- assertConnectionNotNull(conn);
- assertSqlNotNull(sql);
- assertRowMapperNotNull(rowMapper);
- return queryFirstInternal(conn, sql, params, rowMapper);
- }
-
- /**
- * 查询第一行第一列,并转换为指定类型
- *
- * @param 目标类型
- * @param sql SQL
- * @param params 参数
- * @param clazz 目标类型
- */
- private static Optional queryFirst(Connection conn, String sql, Object[] params, Class clazz)
- throws SQLException {
- assertConnectionNotNull(conn);
- assertSqlNotNull(sql);
- assertClazzNotNull(clazz);
- return queryFirstInternal(conn, sql, params, (rs, rowNumber) -> rs.getObject(1, clazz));
- }
-
- /**
- * 查询第一行第一列,并转换为字符串
- *
- * @param conn 数据库连接
- * @param sql SQL
- * @param params 参数
- */
- private static Optional queryFirstString(Connection conn, String sql, Object[] params)
- throws SQLException {
- return queryFirst(conn, sql, params, (rs, rowNumber) -> rs.getString(1));
- }
-
- /**
- * 查询第一行第一列,并转换为整数值
- *
- * @param conn 数据库连接
- * @param sql SQL
- * @param params 参数
- */
- private static OptionalInt queryFirstInt(Connection conn, String sql, Object[] params)
- throws SQLException {
- Optional result = queryFirst(conn, sql, params, (rs, rowNumber) -> rs.getInt(1));
- return OptionalTools.toOptionalInt(result);
- }
-
- /**
- * 查询第一行第一列,并转换为长整型
- *
- * @param conn 数据库连接
- * @param sql SQL
- * @param params 参数
- */
- private static OptionalLong queryFirstLong(Connection conn, String sql, Object[] params)
- throws SQLException {
- Optional result = queryFirst(conn, sql, params, (rs, rowNumber) -> rs.getLong(1));
- return OptionalTools.toOptionalLong(result);
- }
-
- /**
- * 查询第一行第一列,并转换为双精度浮点型
- *
- * @param conn 数据库连接
- * @param sql SQL
- * @param params 参数
- */
- private static OptionalDouble queryFirstDouble(Connection conn, String sql, Object[] params)
- throws SQLException {
- Optional result = queryFirst(conn, sql, params, (rs, rowNumber) -> rs.getDouble(1));
- return OptionalTools.toOptionalDouble(result);
- }
-
- /**
- * 查询第一行第一列,并转换为 {@link BigDecimal}
- *
- * @param conn 数据库连接
- * @param sql SQL
- * @param params 参数
- */
- private static Optional queryFirstBigDecimal(Connection conn, String sql, Object[] params)
- throws SQLException {
- return queryFirst(conn, sql, params, (rs, rowNumber) -> rs.getBigDecimal(1));
- }
-
- // #endregion
-
- // #region - update & batchUpdate
-
- /**
- * 执行更新操作
- *
- * @param conn 数据库连接
- * @param sql 要执行的 SQL
- * @param params 参数
- * @return 更新记录数
- */
- private static int update(Connection conn, String sql, Object[] params)
- throws SQLException {
- assertConnectionNotNull(conn);
- assertSqlNotNull(sql);
- try (PreparedStatement stmt = conn.prepareStatement(sql)) {
- fillStatement(stmt, params);
- return stmt.executeUpdate();
- }
- }
-
- /**
- * 执行 SQL 并返回生成的 keys
- *
- * @param conn 数据库连接
- * @param sql 要执行的 SQL
- * @param params 参数
- * @param rowMapper 行数据映射逻辑
- *
- * @return generated keys
- * @throws SQLException 执行 SQL 遇到异常情况将抛出
- */
- private static List update(Connection conn, String sql, Object[] params, RowMapper rowMapper)
- throws SQLException {
- assertConnectionNotNull(conn);
- assertSqlNotNull(sql);
- assertRowMapperNotNull(rowMapper);
- final List result = new ArrayList<>();
- try (PreparedStatement stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) {
- fillStatement(stmt, params);
- stmt.executeUpdate();
- try (ResultSet generatedKeys = stmt.getGeneratedKeys();) {
- int rowNumber = 0;
- while (generatedKeys.next()) {
- T e = rowMapper.mapRow(generatedKeys, rowNumber++);
- result.add(e);
- }
- }
- return result;
- }
- }
-
- /**
- * 执行批量更新,批量更新数据,返回每条记录更新的行数
- *
- * @param conn 数据库连接
- * @param sql SQL 语句
- * @param params 参数列表
- * @param batchSize 每次批量更新的数据量
- */
- private static List batchUpdate(Connection conn, String sql, Collection params, int batchSize)
- throws SQLException {
- assertConnectionNotNull(conn);
- assertSqlNotNull(sql);
-
- if (params == null || params.isEmpty()) {
- return Collections.emptyList();
- }
- int executeCount = params.size() / batchSize;
- executeCount = (params.size() % batchSize == 0) ? executeCount : (executeCount + 1);
- List result = Lists.newArrayListWithCapacity(executeCount);
-
- try (PreparedStatement stmt = conn.prepareStatement(sql)) {
- int i = 0;
- for (Object[] ps : params) {
- i++;
- fillStatement(stmt, ps);
- stmt.addBatch();
- if (i % batchSize == 0 || i >= params.size()) {
- int[] n = stmt.executeBatch();
- result.add(n);
- stmt.clearBatch();
- }
- }
- return result;
- }
- }
-
- /**
- * 批量更新,返回更新成功的记录行数。发生异常时不中断操作,将异常存入 {@code exceptions} 中
- *
- * @param conn 数据库连接
- * @param sql sql语句
- * @param params 参数列表
- * @param batchSize 每次批量更新的数据量
- * @param exceptions 异常列表,用于记录异常信息
- */
- private static List batchUpdateAndIgnoreException(Connection conn,
- String sql, @Nullable Collection params, int batchSize,
- List exceptions)
- throws SQLException {
- assertConnectionNotNull(conn);
- assertSqlNotNull(sql);
- AssertTools.checkArgument(CollectionTools.isNotEmpty(exceptions),
- "The list used to store exceptions should be non-null and empty.");
- if (params == null || params.isEmpty()) {
- return Collections.emptyList();
- }
- int executeCount = params.size() / batchSize;
- executeCount = (params.size() % batchSize == 0) ? executeCount : (executeCount + 1);
- List result = Lists.newArrayListWithCapacity(executeCount);
-
- try (PreparedStatement stmt = conn.prepareStatement(sql)) {
- int i = 0;
- for (Object[] ps : params) {
- i++;
- fillStatement(stmt, ps);
- stmt.addBatch();
- final int batchIndex = i % batchSize;
- if (batchIndex == 0 || i >= params.size()) {
- try {
- int[] n = stmt.executeBatch();
- result.add(n);
- stmt.clearBatch();
- }
- catch (Exception e) {
- int n = (i >= params.size() && batchIndex != 0) ? batchIndex : batchSize;
- result.add(new int[n]);
- stmt.clearBatch();
- // 收集异常信息
- exceptions.add(e);
- }
- }
- }
- return result;
- }
- }
-
- /**
- * 填充参数
- */
- private static void fillStatement(@Nonnull PreparedStatement stmt, @Nullable Object[] params)
- throws SQLException {
- if (params != null && params.length > 0) {
- Object param;
- for (int i = 0; i < params.length; i++) {
- param = params[i];
- if (param instanceof java.sql.Date) {
- stmt.setDate(i + 1, (java.sql.Date) param);
- }
- else if (param instanceof java.sql.Time) {
- stmt.setTime(i + 1, (java.sql.Time) param);
- }
- else if (param instanceof java.sql.Timestamp) {
- stmt.setTimestamp(i + 1, (java.sql.Timestamp) param);
- }
- else {
- stmt.setObject(i + 1, param);
- }
- }
- }
- }
-
- // #region - 参数校验
-
- private static void assertConnectionNotNull(Connection conn) {
- AssertTools.checkArgumentNotNull(conn, "The argument \"conn\" could not be null.");
- }
-
- private static void assertSqlNotNull(String sql) {
- AssertTools.checkArgumentNotNull(sql, "The argument \"sql\" could not be null.");
- }
-
- private static void assertRowMapperNotNull(RowMapper> rowMapper) {
- AssertTools.checkArgumentNotNull(rowMapper, "The argument \"rowMapper\" could not be null.");
- }
-
- private static void assertResultHandlerNotNull(ResultHandler> resultHandler) {
- AssertTools.checkArgumentNotNull(resultHandler, "The argument \"resultHandler\" could not be null.");
- }
-
- private static void assertClazzNotNull(Class> clazz) {
- AssertTools.checkArgumentNotNull(clazz, "The argument \"clazz\" could not be null.");
- }
-
- // #endregion
}
+
}