10

From Java, I'm calling a prepared statement in Postgresql with an insert that has a RETURNING clause for my identity column. In PG admin it comes right back, but not sure how to get it from my prepared statement:

        String insertStatement = "INSERT INTO person(\n" +
                "            name, address, phone, customer_type, \n" +
                "            start_dtm)\n" +
                "    VALUES (?, ?, ?, ?, \n" +
                "            ?)\n" +
                "    RETURNING person_id;";


        PreparedStatement stmt = connection.prepareStatement(insertStatement);

        stmt.setObject(1, perToSave.getName(null));
        stmt.setObject(2, editToSave.getAddress());
        stmt.setObject(3, editToSave.getPhone());
        stmt.setObject(4, editToSave.getCustType());
        long epochTime = java.lang.System.currentTimeMillis();
        stmt.setObject(5, new java.sql.Date(epochTime));

        stmt.executeUpdate();
Jeff
  • 337
  • 1
  • 3
  • 13

4 Answers4

25

I do not have enough reputation to Comment and my Edit got rejected, so sorry for re-posting the already accepted answer from hd1.

executeUpdate expects no returns; use execute. Check if there is some results before trying to retrieve the value.

String insertStatement = "INSERT INTO person(\n" +
                "            name, address, phone, customer_type, \n" +
                "            start_dtm)\n" +
                "    VALUES (?, ?, ?, ?, \n" +
                "            ?)\n" +
                "    RETURNING person_id;";

PreparedStatement stmt = connection.prepareStatement(insertStatement);

stmt.setObject(1, perToSave.getName(null));
stmt.setObject(2, editToSave.getAddress());
stmt.setObject(3, editToSave.getPhone());
stmt.setObject(4, editToSave.getCustType());
long epochTime = java.lang.System.currentTimeMillis();
stmt.setObject(5, new java.sql.Date(epochTime));

stmt.execute();
ResultSet last_updated_person = stmt.getResultSet();
if(last_updated_person.next()) {
   int last_updated_person_id = last_updated_person.getInt(1);
}
Community
  • 1
  • 1
Malba
  • 286
  • 5
  • 11
  • 1
    Posting your own answer that completes another user's answer is OK as long as you provide credit (which you did) - see http://meta.stackoverflow.com/a/338292/5375403 It would be a good idea though if you stated clearly how your answer differs from the original one, and why it does so. – Jiri Tousek Nov 24 '16 at 13:49
6

According to the javadoc, PreparedStatement inherits from Statement and the latter contains a getResultSet() method. In other words, try this:

String insertStatement = "INSERT INTO person(\n" +
                "            name, address, phone, customer_type, \n" +
                "            start_dtm)\n" +
                "    VALUES (?, ?, ?, ?, \n" +
                "            ?)\n" +
                "    RETURNING person_id;";


PreparedStatement stmt = connection.prepareStatement(insertStatement);

stmt.setObject(1, perToSave.getName(null));
stmt.setObject(2, editToSave.getAddress());
stmt.setObject(3, editToSave.getPhone());
stmt.setObject(4, editToSave.getCustType());
long epochTime = java.lang.System.currentTimeMillis();
stmt.setObject(5, new java.sql.Date(epochTime));

stmt.execute();
ResultSet last_updated_person = stmt.getResultSet();
last_updated_person.next();
int last_updated_person_id = last_updated_person.getInt(1);

Leave a comment if you have further issues.

hd1
  • 33,938
  • 5
  • 80
  • 91
  • 9
    executeUpdate() throws a "org.postgresql.util.PSQLException: A result was returned when none was expected. " as it's not supposed to see a result returned. also getresultSet() without a next call throughs : org.postgresql.util.PSQLException: ResultSet not positioned properly, perhaps you need to call next. – Omid S. Jun 27 '17 at 21:15
  • This answer uses "executeUpdate", but the correct method to call is "execute", as shown in the highly-upvoted, unaccepted answer. Copy and paste from the next answer :-) – Brian Mar 22 '21 at 00:29
  • this is not a correct answer. Correct upvoted but mistakingly unaccepted answer is below – sergeych Jun 16 '21 at 00:20
4

Calling executeUpdate() expects no result from statement. Call stmt.execute() and then stmt.getResultSet()

hd1
  • 33,938
  • 5
  • 80
  • 91
cardamo
  • 853
  • 4
  • 13
3

JDBC has built-in support for returning primary key values for insert statements. Remove the "returning" clause from your SQL and specify PreparedStatement.RETURN_GENERATED_KEYS as a second parameter to your prepareStatment(...) call. Then you can get the generated primary key by calling stmt.getGeneratedKeys() on your PreparedStatement object after calling executeUpdate().

String insertStatement = "INSERT INTO person(\n" +
    "            name, address, phone, customer_type, \n" +
    "            start_dtm)\n" +
    "    VALUES (?, ?, ?, ?, \n" +
    "            ?)";

PreparedStatement stmt = connection.prepareStatement(insertStatement,
    PreparedStatement.RETURN_GENERATED_KEYS);

stmt.setObject(1, perToSave.getName(null));
stmt.setObject(2, editToSave.getAddress());
stmt.setObject(3, editToSave.getPhone());
stmt.setObject(4, editToSave.getCustType());
long epochTime = java.lang.System.currentTimeMillis();
stmt.setObject(5, new java.sql.Date(epochTime));

stmt.executeUpdate();
    
ResultSet resultSet = stmt.getGeneratedKeys();
resultSet.next();
int lastInsertedPersonID = resultSet.getInt(1);
Jerod
  • 31
  • 2