ResultSet中的虚假数据

时间:2018-04-20 00:01:51

标签: java database oracle jdbc resultset

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

这是我的关系:

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);
        }

这一切都很好。但我的问题是密钥应该是整数,而不是字符串。每次运行时,我都会得到一个ResultSet,其中包含一个" AAA3vaAAGAAAFwbAAG"的字符串,或者沿着这些行的东西。我想获取person_id,以便稍后在我的Java程序中使用它。

在搜索ResultSet或执行语句本身方面,我有什么问题吗?

2 个答案:

答案 0 :(得分:5)

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,它将是一个精度为5的整数类型,意味着最多五位数的数字。因此,通过调用ResultSet::getInt将其作为Java中的整数类型检索。

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,请参阅Answer by Mark Rotteveel,解释Oracle数据库在调用getGeneratedKeys时返回生成的序列号。而是返回ROWID pseudo-column

答案 1 :(得分:1)

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

  

如果未明确指示键列,则为Oracle JDBC驱动程序   无法识别需要检索哪些列。当列名   或者使用列索引数组,Oracle JDBC驱动程序可以识别哪些   列包含要检索的自动生成的键。   但是,Statement.RETURN_GENERATED_KEYS整数标志是   使用时,Oracle JDBC驱动程序无法识别这些列。当。。。的时候   整数标志用于指示自动生成的密钥   返回,ROWID伪列作为键返回。 ROWID   然后可以从ResultSet对象中获取并可以用于   检索其他列。

因此,如果您使用Statement.RETURN_GENERATED_KEYS,您将获得ROWID,然后您可以使用该ROWID选择插入的行以获取其他值(包括生成的标识符)。

如果您想专门检索生成的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);
}