【问题标题】:Unexpected IncorrectResultSizeDataAccessException when querying Oracle db查询 Oracle db 时出现意外的 IncorrectResultSizeDataAccessException
【发布时间】:2023-03-05 05:17:01
【问题描述】:

我有下表:

  create table INTERNATIONALIZATION (
    ID number not null unique,
    LANG char(2) not null,
    EXT_ID number not null,
    EXT_COLUMN char(32) not null,
    EXT_NAME char(32) not null,
    TRANS_VAL nvarchar2(512) not null
  );

以下代码旨在从中检索一个且仅一个结果(我 100% 确定该记录存在)。

public Optional<String> getTranslation(long idSkill, Locale lang, String extColumn, String extName) {
    try {
        return Optional.of(jdbcTemplate.queryForObject("select TRANS_VAL from INTERNATIONALIZATION where ext_id = ? and lang = ? and ext_column = ? and ext_name = ?", String.class, idSkill, lang.toLanguageTag(), extColumn, extName));
    } catch (IncorrectResultSizeDataAccessException ex) {
        return Optional.empty();
    }
}

问题是当我总是得到Optional.empty() 时,IncorrectResultSizeDataAccessException 被抛出,因为没有找到记录。

当我在 Oracle SQL Developer 中执行这个 sql 查询时,我得到了正确的结果。

是什么导致了这个问题?是否与nvarchar2 类型的所需列有关?

【问题讨论】:

标签: java oracle spring-jdbc jdbctemplate nvarchar


【解决方案1】:

您可能需要验证传递给查询的参数。它们可能与您在 Oracle SQL Developer 中使用的不同。

对于调试,当您捕获异常时,打印使用的值。

    try {
            return Optional.of(jdbcTemplate.queryForObject("select TRANS_VAL from INTERNATIONALIZATION where ext_id = ? and lang = ? and ext_column = ? and ext_name = ?", String.class, idSkill, lang.toLanguageTag(), extColumn, extName));
        } catch (IncorrectResultSizeDataAccessException ex) {
            return Optional.empty();
          // print idSkill, lang.toLanguageTag(), extColumn, extName here
        }

此外,由于您使用的是 CHAR 列,因此在比较时必须注意填充的空格。由于您使用的是绑定变量,因此在比较 chars 和 varchars 时可能会出现问题。

创建了一个测试表:
SQL> 创建表 t1 (c1 char(5));

    Table created.

    SQL> insert into t1 values ('A');

    1 row created.

    SQL> commit;

    Commit complete.

对比字面量,没问题:

    SQL> select count(*) from t1 where c1 = 'A'; 

      COUNT(*)
    ----------
         1

    SQL> select count(*) from t1 where c1 = 'A ';

      COUNT(*)
    ----------
         1

由于c1是char列,数据向左填充:

    SQL> select '<'|| c1 || '>' from t1;

    '<'||C1
    -------
    <A    >

与 varchar2 绑定变量比较时

    SQL> var s varchar2(5)
    SQL> exec :s := 'A' ;

    PL/SQL procedure successfully completed.

    SQL> select count(*) from t1 where c1 = :s;

      COUNT(*)
    ----------
         0

数据必须相等(5 个字符 - 一个字母,4 个空格):

    SQL> exec :s :='A    '

    PL/SQL procedure successfully completed.

    SQL> select count(*) from t1 where c1 = :s;

      COUNT(*)
    ----------
         1

这只是一个提示,但我认为您最好使用 varchar2 列:

      create table INTERNATIONALIZATION (
        ID number not null unique,
        LANG varchar2(2) not null,
        EXT_ID number not null,
        EXT_COLUMN varchar2(32) not null,
        EXT_NAME varchar2(32) not null,
        TRANS_VAL nvarchar2(512) not null
      );

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-01
    • 1970-01-01
    • 2021-01-25
    • 2011-07-17
    相关资源
    最近更新 更多