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 } + }