【问题标题】:No results "In" clause in PreparedStatement with 2 objectsPreparedStatement 中没有包含 2 个对象的结果“In”子句
【发布时间】:2019-11-15 04:27:25
【问题描述】:

我花了很多时间来寻找解决方案,但我仍然无法解决。

我找到了一些关于如何将“IN”元素传递到 PreparedStatement 的解决方案,但如果有任何其他解决方案,我很乐意看到,但是,无论如何我有

RowMapper<Map<BigInteger, Status>> mapper = new QueryDescriptionById.RowMapperDescription();

@Override
public Multimap<BigInteger, Status> findObject(BigInteger[] ids) {
    StringBuilder builder = new StringBuilder();
    for (Object id : ids) {
        builder.append("?,");
    }
    String statement = SQL + builder.deleteCharAt(builder.length() - 1).toString() + ")";

    Multimap<BigInteger, Status> multimap = ArrayListMultimap.create();
    intoMap(multimap, getJdbcTemplate().query(statement, ps -> {
        int index = 1;
        for (BigInteger id : ids) {
            ps.setInt(index++, id.intValue());
        }
    }, mapper));
    return multimap;
 }

private void intoMap(Multimap<BigInteger, Status> multimap, List<Map<BigInteger, Status>> list) {
    list.forEach(map -> map.forEach((multimap::put)));
}

class RowMapperDescription implements RowMapper {
        @Override
        public Map<BigInteger, Status> mapRow(ResultSet rs, int rowNum) throws SQLException {
            Status status = new Status();
            Map<BigInteger, Status> map = new HashMap<>();
            BigInteger id = rs.getBigDecimal("ID").toBigInteger();
            BigInteger parentId = rs.getBigDecimal("PARENT_ID").toBigInteger();
            status.setId(id);
            status.setDescription(rs.getString("attempt_status_text"));
            map.put(parentId, status);
            return map;
        }
    }

但是当我只传入 BigInteger[] 1 个元素但当有 2 个或更多元素时,它不会进入我的映射器。

为什么?

附言

我尝试使用 ResultSet 代替 RowMapper

return getJdbcTemplate().query(SQL, ids, resultSet -> {
            Multimap<BigInteger, Status> multimap = ArrayListMultimap.create();
            int rowNum = 0;
            while (resultSet.next()) {
                System.out.println("rownum = " + rowNum);
                mapper.mapRow(resultSet, rowNum++).forEach(multimap::put);
            }
            return multimap;
        })

但是在控制台中没有任何行,这意味着结果集没有next()

附言

我的SQL 很难,所以我只放了一个简短的版本。好像

private String SQL = "select el1,el2 from mytable where el3 in(";

我尝试过 in(";in :IDin = :IDin (:ID)in (?) 以及其他一些我不记得的变体(-:

已编辑

其实我不明白,为什么会这样

public QueryDescriptionBySmsId(DataSource dataSource) {
    super(dataSource, SQL);
    logger.debug("Created QueryStatus");
    declareParameter(new SqlParameter("ID", Types.NUMERIC));
    compile();
    logger.debug("Created QueryStatus");
}

@Override
public Multimap<BigInteger, Status> query(Set<BigInteger> ids) {
       Map<String, Set> paramMap = Collections.singletonMap("ID", smsIds);
       List l = executeByNamedParam(paramMap); // it returns a lot of elements which I am looking for
}

但这不起作用

 @Override
 public Multimap<BigInteger, SmsStatus> query(Set<BigInteger> sids) {

        Map<String, Set> paramMap = Collections.singletonMap("ID", ids);
        return getJdbcTemplate().query(SQL,  resultSet -> {
            int rowNum = 0;
            Multimap<BigInteger, SmsStatus> multimap = 
 ArrayListMultimap.create();
            while (resultSet.next()) {
                mapper.mapRow(resultSet, rowNum++).forEach(multimap::put);
            }
            return multimap;
        },paramMap);
 }

显示错误

SQL 状态 [99999];错误代码 [17004];无效的列类型

【问题讨论】:

  • 查询结果是什么样的?似乎SQL 中的部分已经包含左括号...
  • 您使用的是哪个 RDBMS?有些支持传入数组。
  • @Thilo,Oracle,或者你是什么意思:-P
  • @Thilo,链接很好,但我忘了说我使用的是 Spring,我还没有使用 ConnectionStatement。我可以联系getJdbsTemplate() ......我found

标签: java jdbc


【解决方案1】:

我已经像这样更改了我的代码,现在它可以工作了,但我不喜欢那个解决方案

public class QueryDescriptionById extends SqlQuery implements IQueryDescriptionById {

RowMapper<Map<BigInteger, Status>> mapper = new RowMapperDescription();

public QueryDescriptionById(DataSource dataSource) {
    super(dataSource, SQL);
}

public Multimap<BigInteger, SmsStatus> query(Set<BigInteger> ids) {

    Map<String, Set> paramMap = Collections.singletonMap("ID", ids);
    NamedParameterJdbcTemplate template = new NamedParameterJdbcTemplate(getJdbcTemplate().getDataSource());

    return template.query(SQL, paramMap, resultSet -> {
        int rowNum = 0;
        Multimap<BigInteger, Status> multimap = ArrayListMultimap.create();
        while (resultSet.next()) {
            mapper.mapRow(resultSet, rowNum++).forEach(multimap::put);
        }
        return multimap;
    });
}
.........
.........
.........
}

【讨论】:

  • 你不喜欢它什么?您直接将数字列表设置为单个查询参数。这不是理想的解决方案吗?
  • @Thilo,因为我的类扩展了SqlQuery,并且在我之前创建的其他类中,它是通过declareParameter(new SqlParameter("ID", Types.NUMERIC)); compile(); Map&lt;String, Object&gt; params = new HashMap&lt;String, Object&gt;(); params.put("ID", cnrId); return executeByNamedParam(params); 之类的东西实现的,我的意思是,我使用了我的SQL 语句两次,在构造函数和我的query(Set) 方法中。不好
猜你喜欢
  • 2021-02-21
  • 2020-08-27
  • 1970-01-01
  • 2018-03-08
相关资源
最近更新 更多