假设我有三张牌桌:球队,球员,队友。表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?
答案 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() - 它会返回生成密钥的结果集。我相信这就是您所寻找的。 p>
基本上,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);
}