gpt4 book ai didi

java - 当我需要在关闭 ResultSet 之前填充 ResultSet 时,如何抽象出 JDBC 代码?

转载 作者:行者123 更新时间:2023-11-30 01:56:54 27 4
gpt4 key购买 nike

我正在开发一个 Java 应用程序,该应用程序对数据库进行大量 JDBC 查询,每个查询都在一个单独的方法中指定,格式大致如下。

public static void sampleJDBCQuery(String query, DBUtil dbUtil, DataStructure dataStructure) {
ResultSet rs = null;
Handle handle = null;
Connection conn = null;
Statement stmt = null;
LOGGER.debug("Executing query = {}", query);
try {
handle = dbUtil.getConnectionHandle();
conn = handle.getConnection();
if (conn != null) {
stmt = conn.createStatement();
if (stmt != null) {
rs = stmt.executeQuery(query);
if (rs != null) {
while (rs.next()) {
// populate dataStructure using rs
}
}
}
}
} catch (Exception e) {
Metrics.markMeter("vertica.read.error");
LOGGER.error(e.getMessage(), e);
} finally {
DBUtil.closeResultSet(rs);
DBUtil.closeStatement(stmt);
DBUtil.close(handle);
LOGGER.debug("Finished query = {}", query);
}
}

通过上述格式的许多不同示例查询(和数据结构类),我的代码库已经大幅增长。我的目标是拥有一个帮助器方法,为我抽象掉大部分 JDBC 逻辑。我的第一个想法是拥有一个具有以下签名的方法。

public static ResultSet executeJDBCQuery(String query, DBUtil dbUtil)

然后我可以循环 ResultSet 的行并填充相关的DataStructure对于每一行。问题是我仍然必须关闭返回的 ResultSet并关闭ResultSet用不同的方法似乎是糟糕的设计。

我想我正在寻找的东西可能类似于Python的函数装饰器概念,这样我就可以“装饰”一个JDBC查询来处理sampleJDBCQuery中存在的大部分样板文件。多于。我怎样才能实现这个目标?

最佳答案

您可以传入一个策略来告诉该方法如何将行映射到对象上的字段。

这就是 spring-jdbc 所做的,它定义了 RowMapper如:

public interface RowMapper<T> {
T mapRow(ResultSet resultSet, int rowNum) throws SQLException;
}

这是您可以更改方法的方法,包括合并 rowMapper:

public static <T> List<T> queryList(String query, Connection conn, RowMapper<T> rowMapper) throws SQLException {
LOGGER.debug("Executing query = {}", query);
try {
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(query);
List<> list = new ArrayList<>();
while (rs.next()) {
list.add(rowMapper.mapRow(rs, list.size() + 1));
}
return list;
} finally {
DBUtil.closeResultSet(rs);
DBUtil.closeStatement(stmt);
LOGGER.debug("Finished query = {}", query);
}
}

在这里捕获所有异常并不好,因为如果出现问题,您希望能够使用异常来退出当前操作。否则,日志中将有多个错误堆栈跟踪,其中一个是错误发生的地方,另一个是下游,当代码期望出现不是由于上一个错误而导致的结果时,代码会失败。当第一个错误发生时,快速失败。

下一步将参数化您的查询,这样您就不必将参数值括在引号中或担心 SQL 注入(inject)。请参阅this answer有关 spring-jdbc 如何处理此问题的示例。

我将连接内容移出方法;传入连接允许您在同一个 JDBC 本地事务中执行多个 sql 语句。 (连接仍然需要关闭,这只是错误的地方。)

在这里传递这个句柄也违反了 the Law of Demeter :

In particular, an object should avoid invoking methods of a member object returned by another method. For many modern object oriented languages that use a dot as field identifier, the law can be stated simply as "use only one dot". That is, the code a.b.Method() breaks the law where a.Method() does not. As an analogy, when one wants a dog to walk, one does not command the dog's legs to walk directly; instead one commands the dog which then commands its own legs.

即使您只执行只读操作,让查询共享事务也可以提高一致性并提高性能。在 Spring 中使用事务不会那么痛苦,您可以使用注释以声明方式实现事务,以显示您想要的边界位置。

这里的总体答案是:最好采用一个预先存在的工具(spring-jdbc或类似的东西),它们已经解决了你还没有时间考虑的问题,而不是一点点地重新改造它,这显然是你正在走的路。

关于java - 当我需要在关闭 ResultSet 之前填充 ResultSet 时,如何抽象出 JDBC 代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54136465/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com