我正在使用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 LONGVARCHAR和Use 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)
方法,应在其中传递参数类型。