1

目标是编写一个方便的方法,该方法使用简单的客户端调用表单从 JDBC 查询返回 ResultSet。

我写了这样的东西:

public class JdbcQueryManager {
  public static ResultSet executePreparedStatementWithParameters(
      Connection jdbcConnection, String sqlQuery,
      Map.Entry<? extends Class<?>, ?>... sqlQueryParameters)
      throws JdbcQueryFailureException {
    return executePreparedStatementWithParameters(jdbcConnection, sqlQuery,
        Arrays.asList(sqlQueryParameters), ResultSet.TYPE_FORWARD_ONLY,
        ResultSet.CONCUR_READ_ONLY, ResultSet.CLOSE_CURSORS_AT_COMMIT);
  }
  private static ResultSet executePreparedStatementWithParameters(
      Connection jdbcConnection, String sqlQuery,
      List<Map.Entry<? extends Class<?>, ?>> sqlQueryParameters,
      int resultSetType, int resultSetConcurrency, int resultSetHoldability)
      throws JdbcQueryFailureException {
    try {
      PreparedStatement preparedStatement =
          jdbcConnection.prepareStatement(sqlQuery, resultSetType,
              resultSetConcurrency, resultSetHoldability);
      for (int i = 0; i < sqlQueryParameters.size(); i++) {
        int sqlQueryParameterIndex = i + 1; // SQL parameters are 1-based
        Entry<? extends Class<?>, ?> sqlQueryParameter =
            sqlQueryParameters.get(i);
        Class<?> sqlQueryParameterClass = sqlQueryParameter.getKey();
        if (sqlQueryParameterClass == Integer.class) {
          int sqlQueryParameterIntegerValue =
              (Integer) sqlQueryParameter.getValue();
          preparedStatement.setInt(sqlQueryParameterIndex,
              sqlQueryParameterIntegerValue);
        } else if (sqlQueryParameterClass == String.class) {
          String sqlQueryParameterStringValue =
              (String) sqlQueryParameter.getValue();
          preparedStatement.setString(sqlQueryParameterIndex,
              sqlQueryParameterStringValue);
          // TODO: accept other types, not just String and Integer
        } else {
          throw new JdbcQueryFailureException(new IllegalArgumentException(
              sqlQueryParameterClass.getName()));
        }
      }
      ResultSet resultSet = preparedStatement.executeQuery();
      return resultSet;
    } catch (SQLException sqlException) {
      throw new JdbcQueryFailureException(sqlException);
    }
  }
}

使用这个便利类:

public class QueryParameter<T> extends AbstractMap.SimpleEntry<Class<T>, T> {
  @SuppressWarnings("unchecked")
  public QueryParameter(T parameterValue) {
    super((Class<T>) parameterValue.getClass(), parameterValue);
  }
}

能够像这样执行 JDBC SQL 语句:

ResultSet resultSet =
    JdbcQueryManager.executePreparedStatementWithParameters(jdbcConnection,
        sqlQuery, new QueryParameter<String>("AnswerRequest"),
        new QueryParameter<Integer>(42));

...我怎样才能让它变得更好?

具体来说,我的困惑在于使用这种看似复杂、可能不需要的形式:

List<Map.Entry<? extends Class<?>, ?>>
4

1 回答 1

3

传递一个列表没有任何价值Map.Entry<? extends Class<?>, ?>- 你试图告诉你的方法每个参数是什么类。不要这样做!!!

preparedStatement.setXXX()与流行的看法相反,如果您使用“基本”java 对象(包装的原语和),则不需要使用各种类型的方法Dates,只需使用preparedStatement.setObject(index, object)jdbc 驱动程序就会知道该怎么做!

唯一需要使用类型化设置器的情况是您的对象不是“基本”类型之一。如果你真的需要这个,那么只需要instanceof检查每个参数,然后你会写一些代码来提取一个字符串值来使用,但你仍然可以preparedStatement.setObject(index, object)用那个字符串调用。


我自己写过这样的东西,我只是使用:

public static ResultSet executePreparedStatementWithParameters(
    Connection jdbcConnection, String sqlQuery, Object... parameters)

它工作得很好。

于 2012-06-13T14:21:43.417 回答