ResultSet 中的虚假数据

Bogus data in ResultSet

我在使用 JDBC 时遇到了一些问题。

这是我的关系:

create table person (
person_id   number(5) generated always as identity
            minvalue 1
            maxvalue 99999
            increment by 1 start with 1
            cycle
            cache 10,
firstname   varchar(10) not null,
lastname    varchar(10) not null,
);

我正在尝试将 (firstname, lastname) 插入到元组中,然后从中获取 person_id。这是我的 JDBC 代码:

//connection is taken care of beforehand and is named con
prep = con.prepareStatement("insert into person (firstname, lastname) values (?, ?)", Statement.RETURN_GENERATED_KEYS);
        prep.setString(1, firstname);
        prep.setString(2, lastname);
        prep.execute();
        ResultSet generated = prep.getGeneratedKeys();
        if (generated.next()) {
            String key = generated.getString("0");
            System.out.println(key);
        }

一切正常。但我的问题是键应该是一个整数,而不是一个字符串。每次我 运行 这样做时,我都会得到一个包含 "AAA3vaAAGAAAFwbAAG" 字符串或类似内容的结果集。我想获得 person_id 以便稍后在我的 Java 程序中使用它。

在搜索 ResultSet 或执行语句本身方面,我是否做错了什么?

tl;博士

int id = generated.getInt( 1 ) ;

详情

您的问题似乎很混乱。

ResultSet 上的每个 get… 方法有两种形式。

  • 传递列号(int
  • 传递一个列名(一个String

你好像把这两者结合起来了:

String key = generated.getString( "0" ) ;

我怀疑您有一个以单个数字零命名的列。除了名称选择不当之外,标准 SQL 还禁止标识符以数字开头。

所以那句话没有意义。也许您的意思是第一列使用零 0 并错误地将其括在引号中,从而将您预期的 int 转换为实际的 String

即使是这样的意图也是错误的。 ResultSet::getString 文档错误地将 int 描述为“columnIndex”。通常“索引”表示从零开始的计数偏移量。但实际上 ResultSet::getString( int ) 要求您传递一个从 1 开始计数的序数。所以 getString( 0 ) 永远无效。

因此,如果您想将结果集第一列的值作为文本检索,请执行以下操作:

String key = generated.getString( 1 ) ; // Retrieve first column of result set as text.

再一次,这在您的代码上下文中是错误的。您显然是在尝试检索 INSERT 期间生成的主键值。您的主键列 person_id 定义为 number(5),这不是文本类型。所以检索为 String 是不合适的。

NUMBER(5) 不标准 SQL。如果你恰好在使用Oracle数据库,the doc says that would be an integer type with a precision of five, meaning numbers with up to five digits. So retrieve that as a integer type in Java by calling ResultSet::getInt.

int id = generated.getInt( 1 ) ;  // Retrieve the new row’s ID from the first column of the result set of generated key values returned by the `INSERT` prepared statement.

我上面的评论是针对一般数据库的。但具体对于 Oracle,请参阅 explaining that Oracle database does not return the generated sequence number when calling getGeneratedKeys. Instead it returns ROWID pseudo-column.

你的问题是 Oracle 默认 returns 插入记录的 ROWID,而不是生成的标识符。来自 Oracle JDBC Developer's Guide: Retrieval of Auto-Generated Keys:

If key columns are not explicitly indicated, then Oracle JDBC drivers cannot identify which columns need to be retrieved. When a column name or column index array is used, Oracle JDBC drivers can identify which columns contain auto-generated keys that you want to retrieve. However, when the Statement.RETURN_GENERATED_KEYS integer flag is used, Oracle JDBC drivers cannot identify these columns. When the integer flag is used to indicate that auto-generated keys are to be returned, the ROWID pseudo column is returned as key. The ROWID can be then fetched from the ResultSet object and can be used to retrieve other columns.

所以,如果你使用 Statement.RETURN_GENERATED_KEYS,你会得到 ROWID,然后你可以使用那个 ROWID 到 select 插入的行来获取其他值(包括生成的标识符) .

如果您想专门检索生成的 ID,对于 Oracle,您需要按如下方式明确请求该列:

String[] columns = { "PERSON_ID" }
prep = con.prepareStatement(
        "insert into person (firstname, lastname) values (?, ?)", columns);
prep.setString(1, firstname);
prep.setString(2, lastname);
prep.executeUpdate();
ResultSet generated = prep.getGeneratedKeys();
if (generated.next()) {
    int key = generated.getInt("PERSON_ID");
    System.out.println(key);
}