From 93109a004f3e8da09d413dba9029e23023edd8ad Mon Sep 17 00:00:00 2001 From: Michael Bayne Date: Fri, 2 May 2014 13:45:10 -0700 Subject: [PATCH] Yet more lastInsertedId revamping. Third time's the charm. --- .../java/com/samskivert/jdbc/BaseLiaison.java | 18 ++++++++++++++---- .../com/samskivert/jdbc/DatabaseLiaison.java | 5 +++-- .../com/samskivert/jdbc/HsqldbLiaison.java | 9 +++------ .../com/samskivert/jdbc/MySQLLiaison.java | 19 +++++++++++-------- .../samskivert/jdbc/PostgreSQLLiaison.java | 10 +++------- 5 files changed, 34 insertions(+), 27 deletions(-) diff --git a/src/main/java/com/samskivert/jdbc/BaseLiaison.java b/src/main/java/com/samskivert/jdbc/BaseLiaison.java index ac16a36a..d1630465 100644 --- a/src/main/java/com/samskivert/jdbc/BaseLiaison.java +++ b/src/main/java/com/samskivert/jdbc/BaseLiaison.java @@ -38,12 +38,11 @@ public abstract class BaseLiaison implements DatabaseLiaison @Deprecated public int lastInsertedId (Connection conn, String table, String column) throws SQLException { - Integer id = lastInsertedId(conn, null, table, column); - return (id == null) ? -1 : id; + return lastInsertedId(conn, null, table, column); } // from DatabaseLiaison - public Integer lastInsertedId (Connection conn, Statement istmt, String table, String column) + public int lastInsertedId (Connection conn, Statement istmt, String table, String column) throws SQLException { // if this JDBC driver supports getGeneratedKeys, use it! @@ -53,7 +52,18 @@ public abstract class BaseLiaison implements DatabaseLiaison return rs.getInt(column); } } - return null; + return fetchLastInsertedId(conn, table, column); + } + + /** + * Requests the last inserted id for the specified table and column. This is used if a JDBC + * driver does not support {@code getGeneratedKeys} or an attempt to use that failed. + */ + protected int fetchLastInsertedId (Connection conn, String table, String column) + throws SQLException + { + throw new SQLException( + "Unable to obtain last inserted id [table=" + table + ", column=" + column + "]"); } // from DatabaseLiaison diff --git a/src/main/java/com/samskivert/jdbc/DatabaseLiaison.java b/src/main/java/com/samskivert/jdbc/DatabaseLiaison.java index 8843c7a1..0e5d7284 100644 --- a/src/main/java/com/samskivert/jdbc/DatabaseLiaison.java +++ b/src/main/java/com/samskivert/jdbc/DatabaseLiaison.java @@ -55,9 +55,10 @@ public interface DatabaseLiaison * * @param istmt the insert statement that generated the keys. May be null if the ORM doesn't * have the statement handy. - * @return the requested inserted id, or null if no last inserted id can be obtained. + * @return the requested inserted id. + * @throws SQLException if we are unable to obtain the last inserted id. */ - public Integer lastInsertedId (Connection conn, Statement istmt, String table, String column) + public int lastInsertedId (Connection conn, Statement istmt, String table, String column) throws SQLException; /** diff --git a/src/main/java/com/samskivert/jdbc/HsqldbLiaison.java b/src/main/java/com/samskivert/jdbc/HsqldbLiaison.java index 125e812a..09a5fed2 100644 --- a/src/main/java/com/samskivert/jdbc/HsqldbLiaison.java +++ b/src/main/java/com/samskivert/jdbc/HsqldbLiaison.java @@ -72,13 +72,10 @@ public class HsqldbLiaison extends BaseLiaison // HSQL's IDENTITY() does not create any database entities that we need to delete } - @Override // from DatabaseLiaison - public Integer lastInsertedId (Connection conn, Statement istmt, String table, String column) + @Override + protected int fetchLastInsertedId (Connection conn, String table, String column) throws SQLException { - Integer id = super.lastInsertedId(conn, istmt, table, column); - if (id != null) return id; - // HSQL does not keep track of per-table-and-column insertion data, so we are pretty much // going on blind faith here that we're fetching the right ID. In the overwhelming number // of cases that will be so, but it's still not pretty. @@ -86,7 +83,7 @@ public class HsqldbLiaison extends BaseLiaison try { stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("call IDENTITY()"); - return rs.next() ? rs.getInt(1) : null; + return rs.next() ? rs.getInt(1) : super.fetchLastInsertedId(conn, table, column); } finally { JDBCUtil.close(stmt); } diff --git a/src/main/java/com/samskivert/jdbc/MySQLLiaison.java b/src/main/java/com/samskivert/jdbc/MySQLLiaison.java index ec61601d..eb0e4b0b 100644 --- a/src/main/java/com/samskivert/jdbc/MySQLLiaison.java +++ b/src/main/java/com/samskivert/jdbc/MySQLLiaison.java @@ -49,16 +49,19 @@ public class MySQLLiaison extends BaseLiaison // AUTO_INCREMENT does not create any database entities that we need to delete } - @Override // from DatabaseLiaison - public Integer lastInsertedId (Connection conn, Statement istmt, String table, String column) + @Override // from BaseLiaison + public int lastInsertedId (Connection conn, Statement istmt, String table, String column) throws SQLException { - // MySQL hackily reports the last inserted key as GENERATED_KEY, so we call super with that - // "column name"; but if that doesn't work (we're using an old JDBC driver without support - // for returning generated keys), fall back to the old old method - Integer id = super.lastInsertedId(conn, istmt, table, "GENERATED_KEY"); - if (id != null) return id; + // MySQL uses "GENERATED_KEY" as the column name for the last inserted key, so we have to + // hackily pass that to our super method to get things to work + return super.lastInsertedId(conn, istmt, table, "GENERATED_KEY"); + } + @Override + protected int fetchLastInsertedId (Connection conn, String table, String column) + throws SQLException + { // MySQL does not keep track of per-table-and-column insertion data, so we are pretty much // going on blind faith here that we're fetching the right ID. In the overwhelming number // of cases that will be so, but it's still not pretty. @@ -66,7 +69,7 @@ public class MySQLLiaison extends BaseLiaison try { stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("select LAST_INSERT_ID()"); - return rs.next() ? rs.getInt(1) : null; + return rs.next() ? rs.getInt(1) : super.fetchLastInsertedId(conn, table, column); } finally { JDBCUtil.close(stmt); } diff --git a/src/main/java/com/samskivert/jdbc/PostgreSQLLiaison.java b/src/main/java/com/samskivert/jdbc/PostgreSQLLiaison.java index 64084c96..c001cb20 100644 --- a/src/main/java/com/samskivert/jdbc/PostgreSQLLiaison.java +++ b/src/main/java/com/samskivert/jdbc/PostgreSQLLiaison.java @@ -34,14 +34,10 @@ public class PostgreSQLLiaison extends BaseLiaison msg.indexOf("An I/O error occured while sending to the backend") != -1); } - // from DatabaseLiaison - public Integer lastInsertedId (Connection conn, Statement istmt, String table, String column) + @Override + protected int fetchLastInsertedId (Connection conn, String table, String column) throws SQLException { - // try the default first, which uses JDBC's getGeneratedKeys mechanism - Integer id = super.lastInsertedId(conn, istmt, table, column); - if (id != null) return id; - // PostgreSQL's support for auto-generated ID's comes in the form of appropriately named // sequences and DEFAULT nextval(sequence) modifiers in the ID columns. To get the next ID, // we use the currval() method which is set in a database sessions when any given sequence @@ -50,7 +46,7 @@ public class PostgreSQLLiaison extends BaseLiaison try { ResultSet rs = stmt.executeQuery( "select currval('\"" + table + "_" + column + "_seq\"')"); - return rs.next() ? rs.getInt(1) : null; + return rs.next() ? rs.getInt(1) : super.fetchLastInsertedId(conn, table, column); } finally { JDBCUtil.close(stmt); }