JdbcTemplate.queryForObject无法将参数绑定到查询

时间:2015-04-27 12:34:36

标签: java oracle spring-jdbc

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

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

  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);
    }
    
  2. 这样做。

    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);
    }
    
  3. 这样做。

    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);
    }
    
  4. 样本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());
    }
    
  5. 代码示例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

1 个答案:

答案 0 :(得分:0)

您正在使用哪个春季版本,因为我找不到匹配的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)方法,您应该传递参数类型。