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

vs3odd8k  于 2022-09-18  发布在  Java
关注(0)|答案(4)|浏览(175)

假设我有三张表:Team、PERAY、Team_PERFER。表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_Key:How to get the insert ID in JDBC?的地方

yptwkmov

yptwkmov1#

Oracle JDBC驱动程序不支持getGeneratedKeys()-您在触发器中手动生成密钥,大概是从SEQUENCE生成的。

您可以使用Oracle的RETURNING子句:

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
guicsvcw

guicsvcw2#

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

如果您的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);
}
n6lpvg4x

n6lpvg4x3#

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

基本上,Spring JDBC使用这种方法来检索生成的ID(来自JdbcTemplate类的示例)

一种不太优雅的解决方案是使用Oracle的RETURNING clause,但您必须将插入内容 Package 到存储进程中以取回id

jchrr9hc

jchrr9hc4#

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.

相关问题