简体   繁体   English

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

[英]Getting id after insert within a transaction (Oracle)

Let's say I have three tables: team, player, team_player.假设我有三张表:team、player、team_player。 Table team_player is a bridge table allowing a "many to many" relationship.表 team_player 是一个允许“多对多”关系的桥接表。

When someone wants to create a new team, they specify the initial players on that team.当有人想要创建一个新团队时,他们会指定该团队的初始玩家。

How do I insert both the team and team_player rows in the same transaction?如何在同一事务中同时插入 team 和 team_player 行? That is, I'd like to insert all the team_player records before committing to the new team row.也就是说,我想在提交到新的团队行之前插入所有 team_player 记录。 I am using JDBC and Oracle.我正在使用 JDBC 和 Oracle。

When I try the code below, teamId is filled with a string of letters even though team.id is a number (that is incremented by a trigger).当我尝试下面的代码时,即使 team.id 是一个数字(由触发器递增),teamId 也会填充一串字母。 So, this does not seem to be the id of the record which I just tried to insert (but didnt commit to yet).因此,这似乎不是我刚刚尝试插入的记录的 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();

This is where I read about RETURN_GENERATED_KEYS: How to get the insert ID in JDBC?这是我读到 RETURN_GENERATED_KEYS 的地方: 如何在 JDBC 中获取插入 ID?

The Oracle JDBC Driver does not support getGeneratedKeys() - you are manually generating the keys in your trigger, presumably from a SEQUENCE . Oracle JDBC驱动程序不支持getGeneratedKeys() - 您可以手动生成触发器中的键,可能来自SEQUENCE

You can use Oracle's returning clause: 您可以使用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));

Or grab the last sequence number with a second SQL query: 或者使用第二个SQL查询获取最后一个序列号:

SELECT mysequence.CURRVAL FROM dual

You need to tell the driver which column to return. 您需要告诉驱动程序返回哪个列。

If your ID is populated by a trigger the following will work: 如果您的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);
}

Please refer to Statement.getGeneratedKeys() - it gives you back a resultset of generated keys.I believe this is what you seek. 请参考Statement.getGeneratedKeys() - 它会返回生成密钥的结果集。我相信这就是您所寻求的。

Basically, Spring jdbc uses this approach to retrieve generated ids ( example from JdbcTemplate class ) 基本上,Spring jdbc使用这种方法来检索生成的id( 例如来自JdbcTemplate类

A less elegant solution would be to use Oracle's RETURNING clause , but you'll have to wrap you insert into a stored proc to get back the id 一个不太优雅的解决方案是使用Oracle的RETURNING子句 ,但你必须将你的插入包装到存储过程中以获取id

declare
  autorowid varchar2(100);
begin
  INSERT INTO tablename(USERID,USID,MONTH,YEAR) 
  VALUES('testuser','134659573',2,2022)returning rowid into autorowid;
  dbms_output.put_line(autorowid);
end;

// In the Oracle database, directly run this query and get the rowid. Type same 
// query in java prepared statement.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM