当前位置: 首页 > 知识库问答 >
问题:

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

阚正真
2023-03-14

我正在使用JdbcTemplate。queryForObject(字符串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字节),snb是VARCHAR2(18字节)。

    对于这两种类型,我应该如何将参数绑定到查询中,这有什么不同吗?

    是的,有区别!

    由于CHAR(16字节)是固定长度的,而且我的Java字符串输入只包含15个字符,所以我必须指示Oracle用空格填充输入,直到正好是16个字符。这就是RPAD(:imsi,16,'')的作用。

    我的解决方案基于8.3.1 CHAR、VARCHAR和LONGVARCHAR,并在PreparedStatement的WHERE子句中使用CHAR字段

  • 共有1个答案

    刁璞
    2023-03-14

    您使用的是哪个Spring版本,因为我在jdbcTemboard中找不到与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)方法传递参数类型。

     类似资料:
    • 问题内容: 现在,我需要使用以下结构来将多个参数绑定到mysqli查询中: 我使用以下代码计算出问号的数量,并将其插入查询中: 我的问题是,肯定有一种方法可以动态处理查询中尽可能多的输入。硬编码似乎是处理此问题的一种非常糟糕的方法。 我正在使用PHP版本5.4.10 问题答案: 不幸的是,默认情况下,bind_param()不接受数组而不是单独的变量。但是,自PHP 5.6起,将进行重大改进。 要

    • 问题内容: 这个问题不太可能对将来的访客有所帮助;它仅与较小的地理区域,特定的时间段或极为狭窄的情况(通常不适用于Internet的全球受众)有关。要获得使该问题更广泛适用的帮助,请访问帮助中心。 6年前关闭。 我有一个mysql查询,但无法为其绑定参数 我已经试过了 但我收到了并且出错了: 警告:mysqli_stmt :: bind_param():类型定义字符串中的元素数量与绑定变量的数量不

    • 我制作了一个Azure函数(http触发器),并使用Visual Studio 2019将其部署在门户中。 该函数工作正常,我现在将添加一个绑定到我的CosmosDB。我导航到我的函数,然后单击“集成”。现在我看到了触发器、函数以及输入和输出绑定。 我应该可以在这里添加一个新的输入绑定。但我没有“添加”按钮。我做错了什么?

    • 我在《快速入门指南》中创建了基本的Azure功能。根据教程,这个默认函数应该可以立即工作,但我遇到了一个错误。 功能体: 错误消息: 函数($HttpTriggerCSharp1)错误:Microsoft。蔚蓝色的网络作业。主机:错误索引方法的函数。HttpTriggerCSharp1’。微软蔚蓝色的网络作业。主机:无法将参数“u return”绑定到类型HttpResponseMessage

    • 在执行右键单击项目时收到以下消息 - [1/7/2018 6:48:54 AM]发生了ScriptHost错误[1/7/2018 6:47:54 AM]执行的HTTP请求:{[1/8/2018 6.48:54 AM]Microsoft.Azure.WebJobs.Host:错误索引方法“TestFilesIngestJobs.RunScheduleAync”。Microsoft.Azure.Web

    • 我的spring boot applications controller包含一个方法,如下所示,该方法具有可选的 我的问题是,当我用swagger-ui传递查询参数时,这些值不会绑定到可分页对象。我这么说的原因是它打印pageSize为20是否我传递值5作为查询参数。 请求URL:http://localhost:8080/api/markups?offset=2&pageNumber=1&pa