2011-02-10 33 views
5

我刚刚使用Oracle,因此我要脱离之前已在this SO question中回答过的问题。我似乎无法得到它的工作。下面是我使用的语句:使用JDBC获取Oracle 11g的最后一个插入ID

declare 
    lastId number; 
begin 
INSERT INTO "DB_OWNER"."FOO" 
    (ID, DEPARTMENT, BUSINESS) 
    VALUES (FOO_ID_SEQ.NEXTVAL, 'Database Management', 'Oracle') 
    RETURNING ID INTO lastId; 
end; 

当我打电话executeQuery PreparedStatement的把我所造的,这一切都插入到数据库就好了。但是,我似乎无法弄清楚如何检索ID。返回的ResultSet对象不适用于我。调用

if(resultSet.next()) ... 

产生一个讨厌的SQLException,上面写着:

无法执行取一个PLSQL声明:下一

如何获取lastId?很明显,我做错了。

+0

您可以随时查询'SELECT FOO_ID_SEQ.CURRVAL FROM DUAL'。 – Phil

+2

发布函数或存储过程 - 需要知道是否将'lastid'设置为INOUT参数。 –

+0

如果我必须执行另一个查询,我不能保证它是我刚刚插入的元素的id。那里可能会有另一个查询。 – geowa4

回答

2

使它返回给你(而不是一个过程)的函数。或者,有一个OUT参数的程序。

1

当您准备语句时,将第二个参数设置为RETURN_GENERATED_KEYS。那么你应该可以得到一个ResultSet关闭声明对象。

+0

这是线程安全吗? –

+0

@詹姆斯,可能但这似乎是一个奇怪的问题,因为你真的不应该有多个线程使用相同的键和语句。你可以扩展你的问题吗? – jzd

+0

当然。如果你有一个单独的DAO实例(不同步)并且有多个人在数据库上工作(某种服务器应用程序),这会产生不可靠的行为。我假设数据库以先到先得的方式返回这个值,那么它会适合单个用户应用程序吗?我猜想Hibernate的EntityManager可以处理与状态有关的任何问题(保存与否),使用代理模式或其他方式。 –

1

你是否在存储过程中这样做?根据这Oracle document,它不会与服务器端驱动程序一起使用。

The Oracle server-side internal driver does not support 
the retrieval of auto-generated keys feature.
2

不知道这会的工作,因为我已经清除了我所有的东西甲骨文的电脑,但......

更改申报:

declare 
    lastId OUT number; 

切换您的发言通过在连接上使用prepareCall()从PreparedStatement转换为CallableStatement。然后呼叫之前注册输出参数,并在更新后阅读:

cstmt.registerOutParameter(1, java.sql.Types.NUMERIC); 
cstmt.executeUpdate(); 
int x = cstmt.getInt(1); 
+1

这应该起作用,尽管语句必须包含一个变量'?':删除DECLARE部分,并用'RETURNING ID INTO?'替换'RETURNING ID INTO lastId'。 'getInt'返回一个int :) –

+0

谢谢 - 将x的类型从字节改为int。 –

1

您可以使用Statement.getGeneratedKeys()做到这一点。你只需要确保告诉JDBC你想回来使用该方法重载之一哪些列,如Connection.prepareStatement超载这里:

Connection conn = ... 
PreparedStatement pS = conn.prepareStatement(sql, new String[]{"id"}); 
pS.executeUpdate(); 
ResultSet rS = pS.getGeneratedKeys(); 
if (rS.next()) { 
    long id = rS.getLong("id"); 
    ... 
} 

你不需要做RETURNING x INTO的东西与此,只需使用您想要的基本SQL语句即可。

+1

long id = rS.getLong(“id”);是错误的 - 你必须使用列索引,而不是名称(使用oracle) – Fisher

+0

@Fisher:我绝对使用这种技术(使用列名)和Oracle。也许有些情况/版本/配置与甲骨文,但它不工作。 – ColinD

2

我尝试了Oracle驱动程序v11.2.0.3.0(因为在10.x和11.1.x中有一些错误,请参阅other blog)。以下代码正常工作:

final String sql = "insert into TABLE(SOME_COL, OTHER_COL) values (?, ?)"; 
PreparedStatement ps = con.prepareStatement(sql, new String[] {"ID"}); 
ps.setLong(1, 264); 
ps.setLong(2, 1); 
int executeUpdate = ps.executeUpdate(); 
ResultSet rs = ps.getGeneratedKeys(); 
if (rs.next()) { 
    // The generated id 
    long id = rs.getLong(1); 
    System.out.println("executeUpdate: " + executeUpdate + ", id: " + id); 
}