我正在使用JdbcTemplate.queryForObject(String sql,RowMapper rowMapper,Object ... args)从Oracle获取一行,但一直获取EmptyResultDataAccessException错误的结果大小:预期为1,实际为0。

我已经使用Oracle SQL Developer验证了我的SQL,它会返回1行,就像应该的那样。


这一直失败。

public NgsRecord getUserInfoByImsi(String imsi) throws SQLException {
  String sql = "SELECT snb, timestamp_, user_type, real_exch, act_exch, dev_type, rc FROM port WHERE imsi = ?";

  RowMapper<NgsRecord> mapper = new RowMapper<NgsRecord>() {
      public NgsRecord mapRow(ResultSet rs, int rowNum)
            throws SQLException {
          NgsRecord ngsRecord = new NgsRecord();
          ngsRecord.setTimestamp(rs.getDate("timestamp_"));
          ngsRecord.setUser_type(rs.getString("user_type"));
          ngsRecord.setReal_exch(rs.getString("real_exch"));
          ngsRecord.setAct_exch(rs.getString("act_exch"));
          ngsRecord.setDev_type(rs.getString("dev_type"));
          ngsRecord.setRc(rs.getString("rc"));
          ngsRecord.setSnb(rs.getString("snb"));
          return ngsRecord;
      }
  };
  return this.jdbcTemplate.queryForObject(sql, mapper, imsi);
}

这可行。

public NgsRecord getUserInfoByImsi(String imsi) throws SQLException {
  String sql = "SELECT snb, timestamp_, user_type, real_exch, act_exch, dev_type, rc FROM port WHERE imsi = '" + imsi + "'";

  RowMapper<NgsRecord> mapper = new RowMapper<NgsRecord>() {
      public NgsRecord mapRow(ResultSet rs, int rowNum)
              throws SQLException {
          NgsRecord ngsRecord = new NgsRecord();
          ngsRecord.setTimestamp(rs.getDate("timestamp_"));
          ngsRecord.setUser_type(rs.getString("user_type"));
          ngsRecord.setReal_exch(rs.getString("real_exch"));
          ngsRecord.setAct_exch(rs.getString("act_exch"));
          ngsRecord.setDev_type(rs.getString("dev_type"));
          ngsRecord.setRc(rs.getString("rc"));
          ngsRecord.setSnb(rs.getString("snb"));
          return ngsRecord;
      }
  };
  return this.jdbcTemplate.queryForObject(sql, mapper);
}

这可行。

public NgsRecord getUserInfo(String snb) throws SQLException {
  String sql = "SELECT snb, timestamp_, user_type, real_exch, act_exch, dev_type, rc FROM port WHERE snb = ?";

  RowMapper<NgsRecord> mapper = new RowMapper<NgsRecord>() {
      public NgsRecord mapRow(ResultSet rs, int rowNum)
            throws SQLException {
          NgsRecord ngsRecord = new NgsRecord();
          ngsRecord.setTimestamp(rs.getDate("timestamp_"));
          ngsRecord.setUser_type(rs.getString("user_type"));
          ngsRecord.setReal_exch(rs.getString("real_exch"));
          ngsRecord.setAct_exch(rs.getString("act_exch"));
          ngsRecord.setDev_type(rs.getString("dev_type"));
          ngsRecord.setRc(rs.getString("rc"));
          ngsRecord.setSnb(rs.getString("snb"));
          return ngsRecord;
      }
  };
  return this.jdbcTemplate.queryForObject(sql, mapper, snb);
}

示例1已更新并且可以运行。

public NgsRecord getUserInfoByImsi(String imsi) throws SQLException {
  SqlParameterSource namedParameters = new MapSqlParameterSource().addValue("imsi", imsi);
  String sql = "/*+ INDEX(NGS.PORT IDX_PORT_IMSI) */ SELECT snb, timestamp_, user_type, real_exch, act_exch, dev_type, rc FROM port WHERE imsi = RPAD(:imsi, 16, ' ')";
  return (NgsRecord) namedParameterJdbcTemplate.queryForObject(sql, namedParameters, new NgsRecordRowMapper());
}



代码示例1和3的唯一区别是imsi和snb的Oracle数据类型。 Imsi是CHAR(16 BYTE),而snb是VARCHAR2(18 BYTE)。

对于这两种类型,我应如何将参数绑定到查询上有什么区别?


是的,有区别!


由于CHAR(16 BYTE)是固定长度的,并且我的Java String输入仅包含15个字符,因此我必须指示Oracle用空格填充我的输入,直到恰好是16个字符。那就是RPAD(:imsi,16,'')进入的地方。

我的解决方案基于8.3.1 CHAR, VARCHAR, and LONGVARCHARUse a CHAR field in the WHERE clause in a PreparedStatement

最佳答案

您使用的是哪个春季版本,因为我无法在与之匹配的jdbcTemplate中找到方法
ueryForObject(String sql, RowMapper rowMapper,Object[] args)
您可以参考URL

我只能在下面找到三种使用rowMapper的重载方法

queryForObject(String sql, Object[] args, int[] argTypes, RowMapper rowMapper) ;
queryForObject(String sql, Object[] args, RowMapper rowMapper) ;
queryForObject(String sql, RowMapper rowMapper) ;


看你的问题我建议你使用
queryForObject(String sql, Object[] args, int[] argTypes, RowMapper rowMapper)方法,应在其中传递参数类型。

10-06 05:19