java sql jdbc insert-id

java - ¿Cómo obtener el ID de inserción en JDBC?



sql insert-id (10)

Quiero INSERT un registro en una base de datos (que es Microsoft SQL Server en mi caso) utilizando JDBC en Java. Al mismo tiempo, quiero obtener el ID de inserción. ¿Cómo puedo lograr esto utilizando la API de JDBC?


  1. Crear columna generada

    String generatedColumns[] = { "ID" };

  2. Pasa esta columna geneada a tu declaración

    PreparedStatement stmtInsert = conn.prepareStatement(insertSQL, generatedColumns);

  3. Utilice el objeto ResultSet para obtener las Claves generadas en la declaración

    ResultSet rs = stmtInsert.getGeneratedKeys(); if (rs.next()) { long id = rs.getLong(1); System.out.println("Inserted ID -" + id); // display inserted record }


Con NativeQuery de Hibernate, debe devolver una ResultList en lugar de un SingleResult, porque Hibernate modifica una consulta nativa

INSERT INTO bla (a,b) VALUES (2,3) RETURNING id

me gusta

INSERT INTO bla (a,b) VALUES (2,3) RETURNING id LIMIT 1

si intenta obtener un solo resultado, lo que hace que la mayoría de las bases de datos (al menos PostgreSQL) produzcan un error de sintaxis. Después, puede obtener el ID resultante de la lista (que generalmente contiene exactamente un elemento).


De acuerdo con el error "Función no admitida" al usar Statement.RETURN_GENERATED_KEYS , intente esto:

String[] returnId = { "BATCHID" }; String sql = "INSERT INTO BATCH (BATCHNAME) VALUES (''aaaaaaa'')"; PreparedStatement statement = connection .prepareStatement(sql, returnId); int affectedRows = statement.executeUpdate(); if (affectedRows == 0) { throw new SQLException("Creating user failed, no rows affected."); } try (ResultSet rs = statement.getGeneratedKeys()) { if (rs.next()) { System.out.println(rs.getInt(1)); } rs.close(); }

Donde BRANCHID es el ID generado automáticamente


En lugar de un comment , solo quiero responder post.

Interfaz java.sql.PreparedStatement

  1. columnIndexes «Puede usar la función prepareStatement que acepta columnIndexes y la declaración SQL. Donde columnIndexes permite que los distintivos constantes sean Statement.RETURN_GENERATED_KEYS comment o Statement.NO_GENERATED_KEYS [2], sentencia SQL que puede contener uno o más ''?'' En los marcadores de posición de parámetros.

    SINTAXIS «

    Connection.prepareStatement(String sql, int autoGeneratedKeys) Connection.prepareStatement(String sql, int[] columnIndexes)

    Ejemplo:

    PreparedStatement pstmt = conn.prepareStatement( insertSQL, Statement.RETURN_GENERATED_KEYS );

  1. columnNames « Enumere los columnNames como ''id'', ''uniqueID'', ... en la tabla de destino que contienen las claves generadas automáticamente que deben devolverse. El controlador los ignorará si la instrucción SQL no es una INSERT .

    SINTAXIS «

    Connection.prepareStatement(String sql, String[] columnNames)

    Ejemplo:

    String columnNames[] = new String[] { "id" }; PreparedStatement pstmt = conn.prepareStatement( insertSQL, columnNames );

Ejemplo completo:

public static void insertAutoIncrement_SQL(String UserName, String Language, String Message) { String DB_URL = "jdbc:mysql://localhost:3306/test", DB_User = "root", DB_Password = ""; String insertSQL = "INSERT INTO `unicodeinfo`( `UserName`, `Language`, `Message`) VALUES (?,?,?)"; //"INSERT INTO `unicodeinfo`(`id`, `UserName`, `Language`, `Message`) VALUES (?,?,?,?)"; int primkey = 0 ; try { Class.forName("com.mysql.jdbc.Driver").newInstance(); Connection conn = DriverManager.getConnection(DB_URL, DB_User, DB_Password); String columnNames[] = new String[] { "id" }; PreparedStatement pstmt = conn.prepareStatement( insertSQL, columnNames ); pstmt.setString(1, UserName ); pstmt.setString(2, Language ); pstmt.setString(3, Message ); if (pstmt.executeUpdate() > 0) { // Retrieves any auto-generated keys created as a result of executing this Statement object java.sql.ResultSet generatedKeys = pstmt.getGeneratedKeys(); if ( generatedKeys.next() ) { primkey = generatedKeys.getInt(1); } } System.out.println("Record updated with id = "+primkey); } catch (InstantiationException | IllegalAccessException | ClassNotFoundException | SQLException e) { e.printStackTrace(); } }


En mi caso ->

ConnectionClass objConnectionClass=new ConnectionClass(); con=objConnectionClass.getDataBaseConnection(); pstmtGetAdd=con.prepareStatement(SQL_INSERT_ADDRESS_QUERY,Statement.RETURN_GENERATED_KEYS); pstmtGetAdd.setString(1, objRegisterVO.getAddress()); pstmtGetAdd.setInt(2, Integer.parseInt(objRegisterVO.getCityId())); int addId=pstmtGetAdd.executeUpdate(); if(addId>0) { ResultSet rsVal=pstmtGetAdd.getGeneratedKeys(); rsVal.next(); addId=rsVal.getInt(1); }


Estoy golpeando Microsoft SQL Server 2008 R2 desde una aplicación basada en JDBC de un solo hilo y retirando la última ID sin usar la propiedad RETURN_GENERATED_KEYS o cualquier Estado de Preparación. Parece algo como esto:

private int insertQueryReturnInt(String SQLQy) { ResultSet generatedKeys = null; int generatedKey = -1; try { Statement statement = conn.createStatement(); statement.execute(SQLQy); } catch (Exception e) { errorDescription = "Failed to insert SQL query: " + SQLQy + "( " + e.toString() + ")"; return -1; } try { generatedKey = Integer.parseInt(readOneValue("SELECT @@IDENTITY")); } catch (Exception e) { errorDescription = "Failed to get ID of just-inserted SQL query: " + SQLQy + "( " + e.toString() + ")"; return -1; } return generatedKey; }

Esta entrada de blog aísla muy bien tres opciones principales de "última ID" de SQL Server: http://msjawahar.wordpress.com/2008/01/25/how-to-find-the-last-identity-value-inserted-in-the-sql-server/ - no ha necesitado los otros dos todavía.


Estoy usando SQLServer 2008, pero tengo una limitación de desarrollo: no puedo usar un nuevo controlador para él, tengo que usar "com.microsoft.jdbc.sqlserver.SQLServerDriver" (no puedo usar "com.microsoft.sqlserver.jdbc .SQLServerDriver ").

Es por eso que la solución conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS) lanzó un java.lang.AbstractMethodError para mí. En esta situación, una posible solución que encontré es la antigua sugerida por Microsoft: Cómo recuperar el valor de @@ IDENTITY utilizando JDBC

import java.sql.*; import java.io.*; public class IdentitySample { public static void main(String args[]) { try { String URL = "jdbc:microsoft:sqlserver://yourServer:1433;databasename=pubs"; String userName = "yourUser"; String password = "yourPassword"; System.out.println( "Trying to connect to: " + URL); //Register JDBC Driver Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver").newInstance(); //Connect to SQL Server Connection con = null; con = DriverManager.getConnection(URL,userName,password); System.out.println("Successfully connected to server"); //Create statement and Execute using either a stored procecure or batch statement CallableStatement callstmt = null; callstmt = con.prepareCall("INSERT INTO myIdentTable (col2) VALUES (?);SELECT @@IDENTITY"); callstmt.setString(1, "testInputBatch"); System.out.println("Batch statement successfully executed"); callstmt.execute(); int iUpdCount = callstmt.getUpdateCount(); boolean bMoreResults = true; ResultSet rs = null; int myIdentVal = -1; //to store the @@IDENTITY //While there are still more results or update counts //available, continue processing resultsets while (bMoreResults || iUpdCount!=-1) { //NOTE: in order for output parameters to be available, //all resultsets must be processed rs = callstmt.getResultSet(); //if rs is not null, we know we can get the results from the SELECT @@IDENTITY if (rs != null) { rs.next(); myIdentVal = rs.getInt(1); } //Do something with the results here (not shown) //get the next resultset, if there is one //this call also implicitly closes the previously obtained ResultSet bMoreResults = callstmt.getMoreResults(); iUpdCount = callstmt.getUpdateCount(); } System.out.println( "@@IDENTITY is: " + myIdentVal); //Close statement and connection callstmt.close(); con.close(); } catch (Exception ex) { ex.printStackTrace(); } try { System.out.println("Press any key to quit..."); System.in.read(); } catch (Exception e) { } } }

¡Esta solución funcionó para mí!

¡Espero que esto ayude!


Si es una clave generada automáticamente, puede usar Statement#getGeneratedKeys() para esto. Debe llamarlo al mismo estado de cuenta que el que se usa para INSERT . Primero debe crear la declaración utilizando Statement.RETURN_GENERATED_KEYS para notificar al controlador JDBC que devuelva las claves.

Aquí hay un ejemplo básico:

public void create(User user) throws SQLException { try ( Connection connection = dataSource.getConnection(); PreparedStatement statement = connection.prepareStatement(SQL_INSERT, Statement.RETURN_GENERATED_KEYS); ) { statement.setString(1, user.getName()); statement.setString(2, user.getPassword()); statement.setString(3, user.getEmail()); // ... int affectedRows = statement.executeUpdate(); if (affectedRows == 0) { throw new SQLException("Creating user failed, no rows affected."); } try (ResultSet generatedKeys = statement.getGeneratedKeys()) { if (generatedKeys.next()) { user.setId(generatedKeys.getLong(1)); } else { throw new SQLException("Creating user failed, no ID obtained."); } } } }

Tenga en cuenta que depende del controlador JDBC para saber si funciona. Actualmente, la mayoría de las últimas versiones funcionarán, pero si estoy en lo cierto, el controlador JDBC de Oracle sigue teniendo problemas con esto. MySQL y DB2 ya lo soportaron por años. PostgreSQL comenzó a soportarlo no hace mucho. No puedo comentar sobre MSSQL porque nunca lo he usado.

Para Oracle, puede invocar un CallableStatement con una cláusula RETURNING o un SELECT CURRVAL(sequencename) (o cualquier sintaxis específica de DB para hacerlo) directamente después de INSERT en la misma transacción para obtener la última clave generada. Véase también esta respuesta .


También es posible usarlo con los Statement normales (no solo con PreparedStatement )

Statement statement = conn.createStatement(); int updateCount = statement.executeUpdate("insert into x...)", Statement.RETURN_GENERATED_KEYS); try (ResultSet generatedKeys = statement.getGeneratedKeys()) { if (generatedKeys.next()) { return generatedKeys.getLong(1); } else { throw new SQLException("Creating failed, no ID obtained."); } }


Connection cn = DriverManager.getConnection("Host","user","pass"); Statement st = cn.createStatement("Ur Requet Sql"); int ret = st.execute();