PreparedStatement with Statement.RETURN_GENERATED_KEYS
You can either use the prepareStatement
method taking an additional int
parameter
PreparedStatement ps = con.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)
For some JDBC drivers (for example, Oracle) you have to explicitly list the column names or indices of the generated keys:
PreparedStatement ps = con.prepareStatement(sql, new String[]{"USER_ID"})
Issue with PreparedStatement while using with Statement.RETURN_GENERATED_KEYS
In oracle DB RETURN_GENERATED_KEYS
works in that way.
1) RETURN_GENERATED_KEYS
flag
PreparedStatement ps = con.prepareStatement("INSERT INTO XXX( A, B) VALUES ( xxx_s.nextval, 'aaa')",Statement.RETURN_GENERATED_KEYS);
ps.executeUpdate();
ResultSet rs = ps.getGeneratedKeys();
while(rs.next()) {
System.out.println(rs.getString(1));
}
Oracle doesn't know which column was auto-generated and it is returning rowid
. returning rowid into :?
is appended to the insert
2) List of columns.
PreparedStatement ps = con.prepareStatement("INSERT INTO XXX( A, B) VALUES ( xxx_s.nextval, 'aaa')",new String[]{"A"});
ps.executeUpdate();
ResultSet rs = ps.getGeneratedKeys();
while(rs.next()) {
System.out.println(rs.getString(1));
}
con.close();
In this case we explicitly specify auto generated column. returning a into :?
is appended to the insert
In both case you to access generated column you have to use positional access. Access by column name is not supported.
However you are trying to do insert as select
. Statment is tranformated to
insert into xxxy select * from xxxy returning rowid into :var ;
And this Statement is not supported by oracle db. And exception ORA-00933: SQL command not properly ended is raised
.
PreparedStatement.RETURN_GENERATED_KEYS and Mysql
Since id
is declared as AUTO_INCREMENT
you don't need to mention it in the query:
String sql = "insert into log ( date, user_name, event, message, audio_path) values (?,?,?,?,?)";
In this way MySQL will automatically generate new id.
Then, you should do this:
PreparedStatement ps = connection.prepareStatement(sql, RETURN_GENERATED_KEYS)
ps.setTimestamp(1, log.getDate());
// ...
ps.setString(5, log.getAudioPath());
int updated = ps.executeUpdate();
ResultSet generatedKeysResultSet = ps.getGeneratedKeys();
// first row of this set will contain generated keys
// in our case it will contain only one row and only one column - generated id
generatedKeysResultSet.next(); // executing next() method to navigate to first row of generated keys (like with any other result set)
long id = generatedKeysResultSet.getLong(1); // since our row contains only one column we won't miss with the column index :)
log.setId(id);
return updated;
Besides that, after you try and get working example I would really recommend to correctly close MySQL Connection
and PreparedStatement
using JDBC. Please refer to this answer on how to correctly create and close resources.
Hope this helps
PreparedStatement.RETURN_GENERATED_KEYS not working with batch insert
Is there a way to get the auto generated values during the insertion itself.
No. After you ps.executeBatch()
you need to call ps.getGeneratedKeys()
and loop through the ResultSet it returns.
JDBC PreparedStatement always returns 1 as auto generated key
PreparedStatment.executeUpdate()
Returns:
either (1) the row count for SQL Data Manipulation Language (DML) statements or (2) 0 for SQL statements that return nothing
You need to use execute()
instead and get the ResultSet
with getGeneratedKeys()
; it's going to contain the data you want.
Edit to add: I read your question as there is an auto-increment field in the table that is not userId
Does Statement.RETURN_GENERATED_KEYS generate any extra round trip to fetch the newly created identifier?
In PostgreSQL with PgJDBC there is no extra round-trip to fetch generated keys.
It sends a Parse/Describe/Bind/Execute message series followed by a Sync, then reads the results including the returned result-set. There's only one client/server round-trip required because the protocol pipelines requests.
However sometimes batches that can otherwise be streamed to the server may be broken up into smaller chunks or run one by on if generated keys are requested. To avoid this, use the String[]
array form where you name the columns you want returned and name only columns of fixed-width data types like integer
. This only matters for batches, and it's a due to a design problem in PgJDBC.
(I posted a patch to add batch pipelining support in libpq that doesn't have that limitation, it'll do one client/server round trip for arbitrary sized batches with arbitrary-sized results, including returning keys.)
MySQL Error when using Statement.RETURN_GENERATED_KEYS
Recommend changing your code as follows:
Name the key column
Get the row count from the
executeUpdate
callDon't call
getGeneratedKeys()
if no rows were inserted
rows = stmt.executeUpdate(query, new String[] { "flight_id" });
int autoIncKey = -1;
if (rows > 0) {
result = stmt.getGeneratedKeys();
if (result.next()) {
autoIncKey = result.getInt(1);
}
}
svr.setGeneratedKey(autoIncKey);
obj.setGeneratedKey(autoIncKey);
svr.setRows(rows); //Insert/Update/Delete
svr.setSuccess(rows > 0);
Though, really, a single INSERT
statement using VALUES
will always insert exactly one row, so checking row count is entirely unnecessary. If the row wasn't inserted, an exception would have been thrown, so your code could be reduced to:
stmt.executeUpdate(query, new String[] { "flight_id" });
try (ResultSet result = stmt.getGeneratedKeys()) {
result.next();
int autoIncKey = result.getInt(1);
svr.setGeneratedKey(autoIncKey);
obj.setGeneratedKey(autoIncKey);
}
svr.setRows(1);
svr.setSuccess(true);
Java PreparedStatement RETURN_GENERATED_KEYS not working
My JT400.jar file was an older version. I downloaded the latest jar file from sourceforge and the problem was solved.
Related Topics
Check If a File Is Locked in Java
Garbage Collection on a Local Variable
How to Get the Real Path of Java Application at Runtime
Difference Between List and Array
Array Initialization Differences Java
What Is Inside Com.Sun Package
Use of '? Extends ' and '? Super ' in Collection Generics
Why Isn't This Code Causing a Concurrentmodificationexception
How to Convert Date in to Yyyy-Mm-Dd Format
How to Execute Multiple SQL Statements from Java
How to Compile a Java Source File Which Is Encoded as "Utf-8"
Java: Setcellvaluefactory; Lambda VS. Propertyvaluefactory; Advantages/Disadvantages
How to Handle Simultaneous Key Presses in Java
Last Row Always Removed from Defaulttablemodel, Regardless of Index
Java Int to String - Integer.Tostring(I) VS New Integer(I).Tostring()
How to Test If My Font Is Rendered Correctly in PDF
Java: Object to Byte[] and Byte[] to Object Converter (For Tokyo Cabinet)