【问题标题】:Using spring jdbc template to query for list of parameters使用spring jdbc模板查询参数列表
【发布时间】:2015-11-12 19:44:01
【问题描述】:

Spring JDBC 模板的新手,但我想知道是否能够传递参数列表并为列表中的每个参数执行一次查询。正如我看到的许多示例,传递的参数列表用于使用提供的所有参数执行查询。相反,我试图多次执行查询,并且每次都使用列表中的新参数。

例如: 假设我有一个 ID 列表 - 参数(字符串)

List<String> params = new ArrayList<String>();
params.add("1234");
params.add("2345");

尝试做类似的事情:

getJdbcTemplate().query(sql, params, new CustomResultSetExtractor());

我知道根据文档是不允许的。我的意思是它必须是一个数组。我见过一些简单的例子,其中查询类似于"select * from employee where id = ?",它们将new Object[]{"1234"} 传递给方法。我试图避免 IN() 条件。在我的情况下,每个 id 都会返回多行,这就是我使用 ResultSetExtractor 的原因。

我知道一种选择是遍历列表并将列表中的每个 id 作为参数包含在内,例如:

for(String id : params){
  getJdbcTemplate().query(sql, new Object[]{id}, new CustomResultSetExtractor());
}

只是想知道我是否可以通过其他方式做到这一点。抱歉,我应该提到我正在尝试进行选择。最初希望为每个结果集返回一个自定义对象列表。

【问题讨论】:

  • 也许你可以使用preparedStatement并循环你的id来设置参数,这样也可以节省你的内存和时间。

标签: spring jdbc


【解决方案1】:

您确实需要为 API 传递一个参数数组,但您也可以假设您的第一个参数是一个数组。我相信这应该可行:

String sql = "select * from employee where id in (:ids)"; // or should there be '?'
getJdbcTemplate().query(sql, new Object[]{params}, new CustomResultSetExtractor());

或者您可以明确指定参数是一个数组

getJdbcTemplate().query(sql, new Object[]{params}, new int[]{java.sql.Types.ARRAY}, new CustomResultSetExtractor());

【讨论】:

    【解决方案2】:

    你可以使用preparedStatement做批处理:

    例如。来自http://docs.spring.io/spring/docs/current/spring-framework-reference/html/jdbc.html

    public int[] batchUpdate(final List<Actor> actors) {
            int[] updateCounts = jdbcTemplate.batchUpdate("update t_actor set first_name = ?, " +
                    "last_name = ? where id = ?",
                new BatchPreparedStatementSetter() {
                    public void setValues(PreparedStatement ps, int i) throws SQLException {
                            ps.setString(1, actors.get(i).getFirstName());
                            ps.setString(2, actors.get(i).getLastName());
                            ps.setLong(3, actors.get(i).getId().longValue());
                        }
    
                        public int getBatchSize() {
                            return actors.size();
                        }
                    });
            return updateCounts;
        }
    

    【讨论】:

      【解决方案3】:

      我知道您不想使用 in 子句,但我认为它是解决您问题的最佳方法。

      如果你以这种方式使用for,我认为它不是最佳的。

      for(String id : params){
        getJdbcTemplate().query(sql, new Object[]{id}, new CustomResultSetExtractor());
      }
      

      我认为使用 in 子句是更好的解决方案。然后使用 ResultSetExtractor 迭代结果数据。您的提取器可以返回 Map 而不是 List,实际上是 List 的 Map。

      Map<Integer, List<MyObject>>
      

      这里有一个简单的教程解释它的使用

      http://pure-essence.net/2011/03/16/how-to-execute-in-sql-in-spring-jdbctemplate/

      【讨论】:

      • 好的,我可能会使用 IN 子句...不太确定,因为我可能有数以万计的 ID。
      • 好的,我认为您可以对 ID 使用分页,并一次使用 500 个 ID 进行查询。
      【解决方案4】:

      我认为这是最好的解决方案:

      public List<TestUser> findUserByIds(int[] ids) {
        String[] s = new String[ids.length];
        Arrays.fill(s, "?");
        String sql = StringUtils.join(s, ',');
      
        return jdbcTemplate.query(String.format("select * from users where id in (%s)", sql),
          ArrayUtils.toObject(ids), new BeanPropertyRowMapper<>(TestUser.class));
      }
      

      这可能是你想要的。 BeanPropertyRowMapper 只是一个例子,当有很多记录时它会很慢。您应该将其更改为另一个更高效的 RowMapper。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-10-09
        • 1970-01-01
        • 1970-01-01
        • 2012-12-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多