在事务中插入后获取id(Oracle)

时间:2013-07-03 22:25:23

标签: java sql oracle jdbc

假设我有三张牌桌:球队,球员,队友。表team_player是一个允许“多对多”关系的桥接表。

当有人想要创建新团队时,他们会指定该团队的初始玩家。

如何在同一个交易中插入team和team_player行?也就是说,我想在提交新团队行之前插入所有team_player记录。我正在使用JDBC和Oracle。

当我尝试下面的代码时,即使team.id是一个数字(由触发器递增),teamId也会填充一串字母。所以,这似乎不是我刚刚尝试插入的记录的ID(但还没有提交)。

c = DB.getConnection();
c.setAutoCommit(false);

sql = "INSERT INTO team (name) values (?)";
myInsert = c.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
myInsert.setString(1, "cougars");
int affectedRows = memoInsert.executeUpdate();

String teamId;
ResultSet generatedKeys = myInsert.getGeneratedKeys();
if (generatedKeys.next()) {
    teamId = generatedKeys.getString(1);
}

// ...loop through players inserting each player and team.id into team_player

// c.commit();

这是我读到RETURN_GENERATED_KEYS的地方: How to get the insert ID in JDBC?

3 个答案:

答案 0 :(得分:10)

Oracle JDBC驱动程序不支持getGeneratedKeys() - 您可以在触发器中手动生成密钥,大概来自SEQUENCE

您可以使用Oracle的返回子句:

String query = "BEGIN INSERT INTO team (name) values (?) returning id into ?; END;";
CallableStatement cs = conn.prepareCall(query);
cs.setString(1, "cougars");
cs.registerOutParameter(2, OracleTypes.NUMBER);
cs.execute();
System.out.println(cs.getInt(2));

或者使用第二个SQL查询获取最后一个序列号:

SELECT mysequence.CURRVAL FROM dual

答案 1 :(得分:1)

请参考Statement.getGeneratedKeys() - 它会返回生成密钥的结果集。我相信这就是您所寻找的。

基本上,Spring jdbc使用这种方法来检索生成的id(example from JdbcTemplate class

一个不太优雅的解决方案是使用Oracle的RETURNING clause,但你必须将你的插入包装到存储过程中以获取id

答案 2 :(得分:1)

您需要告诉驱动程序返回哪个列。

如果您的ID由触发器填充,则以下内容将起作用:

sql = "INSERT INTO team (name) values (?)";

// pass an array of column names to be returned by the driver instead of the int value
// this assumes the column is named ID (I think it has to be all uppercase)

myInsert = c.prepareStatement(sql, new String[]{"ID"});

myInsert.setString(1, "cougars");
int affectedRows = memoInsert.executeUpdate();

String teamId;
ResultSet generatedKeys = myInsert.getGeneratedKeys();
if (generatedKeys.next()) {
    teamId = generatedKeys.getString(1);
}
相关问题