Java 如何准备类型为:List<;的参数;进入<;?扩展类<>&燃气轮机&燃气轮机;

Java 如何准备类型为:List<;的参数;进入<;?扩展类<>&燃气轮机&燃气轮机;,java,generics,guava,covariance,Java,Generics,Guava,Covariance,目标是编写一个方便的方法,使用简单的客户端调用表单从JDBC查询返回结果集 我写过这样的东西: public class JdbcQueryManager { public static ResultSet executePreparedStatementWithParameters( Connection jdbcConnection, String sqlQuery, Map.Entry<? extends Class<?>, ?>...

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

我写过这样的东西:

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);
    }
  }
}
ResultSet resultSet =
    JdbcQueryManager.executePreparedStatementWithParameters(jdbcConnection,
        sqlQuery, new QueryParameter<String>("AnswerRequest"),
        new QueryParameter<Integer>(42));
公共类JdbcQueryManager{
公共静态结果集executePreparedStatementWithParameters(
连接jdbcConnection,字符串sqlQuery,
映射条目(sqlQueryParameters)
引发JdbcQueryFailureException{
返回executePreparedStatementWithParameters(jdbcConnection、sqlQuery、,
Arrays.asList(sqlQueryParameters),ResultSet.TYPE\u FORWARD\u,
ResultSet.CONCUR_只读,ResultSet.CLOSE_游标(在提交时);
}
私有静态结果集executePreparedStatementWithParameters(
连接jdbcConnection,字符串sqlQuery,
列表>sqlQueryParameters,
int resultSetType、int resultSetConcurrency、int resultSetHoldability)
引发JdbcQueryFailureException{
试一试{
准备好的报表准备好的报表=
prepareStatement(sqlQuery,resultSetType,
ResultsConcurrency,ResultsTholdability);
对于(int i=0;isqlQueryParameter=
sqlQueryParameters.get(i);
类sqlQueryParameterClass=sqlQueryParameter.getKey();
if(sqlQueryParameterClass==Integer.class){
int sqlQueryParameterIntegerValue=
(整数)sqlQueryParameter.getValue();
preparedStatement.setInt(sqlQueryParameterIndex,
sqlQueryParameterIntegerValue);
}else if(sqlQueryParameterClass==String.class){
字符串sqlQueryParameterStringValue=
(字符串)sqlQueryParameter.getValue();
preparedStatement.setString(sqlQueryParameterIndex,
sqlQueryParameterStringValue);
//TODO:接受其他类型,而不仅仅是字符串和整数
}否则{
抛出新的JdbcQueryFailureException(新的IllegalArgumentException(
sqlQueryParameterClass.getName());
}
}
ResultSet ResultSet=preparedStatement.executeQuery();
返回结果集;
}捕获(SQLException SQLException){
抛出新的JdbcQueryFailureException(sqlException);
}
}
}
使用此便利类:

public class QueryParameter<T> extends AbstractMap.SimpleEntry<Class<T>, T> {
  @SuppressWarnings("unchecked")
  public QueryParameter(T parameterValue) {
    super((Class<T>) parameterValue.getClass(), parameterValue);
  }
}
公共类QueryParameter扩展了AbstractMap.SimpleEntry{
@抑制警告(“未选中”)
公共查询参数(T参数值){
super((Class)parameterValue.getClass(),parameterValue);
}
}
要能够执行如下JDBC SQL语句:

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);
    }
  }
}
ResultSet resultSet =
    JdbcQueryManager.executePreparedStatementWithParameters(jdbcConnection,
        sqlQuery, new QueryParameter<String>("AnswerRequest"),
        new QueryParameter<Integer>(42));
ResultSet ResultSet=
JdbcQueryManager.executePreparedStatementWithParameters(jdbcConnection,
sqlQuery,新的QueryParameter(“AnswerRequest”),
新的QueryParameter(42));
。。。我怎样才能做得更好

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

List<Map.Entry<? extends Class<?>, ?>>
列表>

在传递
Map.Entry的列表时没有任何值,>
-您试图告诉您的方法每个参数是什么类不要这样做

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

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


我自己也写过类似的东西,我只是用:

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

而且它工作正常。

旁注:格式化程序每行至少应接受150个字符。这就是为什么,依我看。为什么。。。什么?:)你的意思是“格式化代码,每行字符数更多”/“更宽”,基本上是吗?我想,你只是在用整个
QueryParameter
的东西使你的生活复杂化。为什么不改用
execute(sqlQuery,“AnswerRequest”,42)
之类的东西呢?我曾经写过这样的东西,它可以工作(使用4个不同的DBs)。你的意思是接受一个“Object…varargs”参数,然后使用“for(Object o:varargs)preparedStatement.setObject(o)?我想这是Bohemian推荐的…我查看了一些实现setObject的JDBC驱动程序的源代码(例如,Xerial的Sqlite、PostreSQL的pgjdbc等),它们中的大多数只是在设置类型之前进行一系列实例检查(Timestamp、Double、Integer、Float.java.util.Date等)。您在“不要这样做!”中强调了很多!!!“好像它有一些危害,它只是多余的,因此引入了不必要的潜在错误源,由于重复而违反了DRY。有趣的是,你自己也做了类似的事情,你能分享代码吗?”?