1 回答
TA贡献1890条经验 获得超9个赞
您可以传入一个策略来告诉该方法如何将行映射到对象上的字段。
这就是 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 注入。有关spring-jdbc 如何处理此问题的示例,请参见此答案。
我把连接的东西移出了方法;传入连接允许您在同一个 JDBC 本地事务中执行多个 sql 语句。(连接仍然需要关闭,这只是错误的地方。)
同样在这里传递这个句柄是违反德墨忒耳法则的:
特别是,一个对象应该避免调用另一个方法返回的成员对象的方法。对于许多使用点作为字段标识符的现代面向对象语言,该法则可以简单地表述为“仅使用一个点”。也就是说,代码 abMethod() 违反了 a.Method() 没有的规律。打个比方,想让狗走路,不是直接命令狗腿走路,而是直接让狗走路。取而代之的是命令狗,然后狗命令自己的腿。
即使您只做只读的事情,让查询共享事务也可以提高一致性并提高性能。使用 Spring 使用事务不那么痛苦,您可以使用注释以声明方式实现事务,以显示您希望边界在哪里。
这里的全局答案是:最好采用一个预先存在的工具(spring-jdbc 或类似的东西),它们已经解决了你甚至还没有考虑过的问题,而不是零碎地重新发明它,这就是你显然要走的路。
添加回答
举报