Reputation: 626
Let's say I have three tables: team, player, team_player. Table team_player is a bridge table allowing a "many to many" relationship.
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? That is, I'd like to insert all the team_player records before committing to the new team row. I am using JDBC and 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). So, this does not seem to be the id of the record which I just tried to insert (but didnt commit to yet).
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?
Upvotes: 7
Views: 18211
Reputation: 1
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.
Upvotes: 0
Reputation:
You need to tell the driver which column to return.
If your ID is populated by a trigger the following will work:
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);
}
Upvotes: 4
Reputation: 4048
The Oracle JDBC Driver does not support getGeneratedKeys()
- you are manually generating the keys in your trigger, presumably from a SEQUENCE
.
You can use Oracle's returning clause:
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:
SELECT mysequence.CURRVAL FROM dual
Upvotes: 12
Reputation: 3610
Please refer to Statement.getGeneratedKeys() - it gives you back a resultset of generated keys.I believe this is what you seek.
Basically, Spring jdbc uses this approach to retrieve generated ids (example from JdbcTemplate class)
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
Upvotes: 1