2009-09-03 21 views
48

¿Hay alguna manera de recuperar la clave generada automáticamente de una consulta DB cuando se utiliza una consulta java con sentencias preparadas?¿Hay alguna manera de recuperar el autoincrement ID de una instrucción preparada?

Por ejemplo, sé que AutoGeneratedKeys puede funcionar de la siguiente manera.

stmt = conn.createStatement(); 

stmt.executeUpdate(sql, Statement.RETURN_GENERATED_KEYS); 
if(returnLastInsertId) { 
    ResultSet rs = stmt.getGeneratedKeys(); 
    rs.next(); 
    auto_id = rs.getInt(1); 
} 

Sin embargo. ¿Qué sucede si quiero hacer una inserción con una Declaración preparada?

String sql = "INSERT INTO table (column1, column2) values(?, ?)"; 
stmt = conn.prepareStatement(sql); 

//this is an error 
stmt.executeUpdate(Statement.RETURN_GENERATED_KEYS); 
if(returnLastInsertId) { 
    //this is an error since the above is an error 
    ResultSet rs = stmt.getGeneratedKeys(); 
    rs.next(); 
    auto_id = rs.getInt(1); 
} 

Hay una manera de hacer esto que no conozco. Parece desde el javadoc que PreparedStatements no puede devolver el ID generado automáticamente.

+0

returnLastInsertId de dónde sacas esta variable – dedpo

Respuesta

84

Sí. Ver here. Sección 7.1.9. Cambie su código a:

String sql = "INSERT INTO table (column1, column2) values(?, ?)"; 
stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS); 


stmt.executeUpdate(); 
if(returnLastInsertId) { 
    ResultSet rs = stmt.getGeneratedKeys(); 
    rs.next(); 
    auto_id = rs.getInt(1); 
} 
+0

Esto no funciona de Oracle. –

+8

@JafarAli, esta pregunta es sobre mysql. En Oracle, debe especificar [la columna generada] (https://community.oracle.com/thread/338591) o usar la Id. De fila. – Yishai

+1

¿Olvidaste a 'rs.close()'? Es necesario ? – Winter

2

Sí, hay una manera. Acabo de encontrar este escondite en el documento de Java.

Ellos manera es pasar el id AutoGeneratedKeys de la siguiente manera

String sql = "INSERT INTO table (column1, column2) values(?, ?)"; 
stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS); 
3

Hay un par de maneras, y parece diferentes controladores JDBC maneja las cosas un poco diferentes, o nada en absoluto en algunos casos (algunos sólo das que autogenerado claves primarias, no otras columnas), pero las formas básicas son

stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS); 

o utilizar este formulario:

String autogenColumns[] = {"column1","column2"}; 
stmt = conn.prepareStatement(sql, autogenColumns) 
1

Soy uno de esos que navegaron por algunos hilos buscando la solución a este problema ... y finalmente lo pusieron a trabajar. Para aquellos que utilizan jdbc: oracle: thin: con ojdbc6.jar favor, tome nota: Puede utilizar cualquiera de los métodos: (método 1)

Try{ 
    String yourSQL="insert into Table1(Id,Col2,Col3) values(SEQ.nextval,?,?)"; 
    myPrepStatement = <Connection>.prepareStatement(yourSQL, Statement.RETURN_GENERATED_KEYS); 
    myPrepStatement.setInt(1, 123); 
    myPrepStatement.setInt(2, 123); 

    myPrepStatement.executeUpdate(); 
    ResultSet rs = getGeneratedKeys; 
    if(rs.next()) { 
     java.sql.RowId rid=rs.getRowId(1); 
     //what you get is only a RowId ref, try make use of it anyway U could think of 
     System.out.println(rid); 
    } 
} catch (SQLException e) { 
    // 
} 

(método 2)

Try{ 
    String yourSQL="insert into Table1(Id,Col2,Col3) values(SEQ.nextval,?,?)"; 
    //IMPORTANT: here's where other threads don tell U, you need to list ALL cols 
    //mentioned in your query in the array 
    myPrepStatement = <Connection>.prepareStatement(yourSQL, new String[]{"Id","Col2","Col3"}); 
    myPrepStatement.setInt(1, 123); 
    myPrepStatement.setInt(2, 123); 
    myPrepStatement.executeUpdate(); 
    ResultSet rs = getGeneratedKeys; 
    if(rs.next()) { 
    //In this exp, the autoKey val is in 1st col 
    int id=rs.getLong(1); 
    //now this's a real value of col Id 
    System.out.println(id); 
    } 
} catch (SQLException e) { 
    // 
} 

Básicamente, tratar Método 1 no usado si solo quiere el valor de SEQ.Nextval, pero simplemente devuelve el ref de RowID que puede descifrar su cabeza encontrando la manera de usarlo, ¡que tampoco se ajusta a todo tipo de datos que intentó usar para lanzarlo! Esto puede funcionar bien (return real val) en MySQL, DB2 pero no en Oracle.

Y, apague su SQL Developer, Toad o cualquier cliente que use la misma sesión de inicio de sesión para realizar INSERT cuando esté depurando. PUEDE que no le afecte cada vez (llamada de depuración) ... hasta que encuentre sus aplicaciones congeladas sin excepción por algún tiempo. Sí ... detener sin excepción!

+0

'executeUpdate()' no devuelve un 'ResultSet', devuelve un' int', que es el conteo de actualizaciones. Debe recuperar las claves generadas por separado. Vea las respuestas existentes, y el Javadoc por el amor de Dios. -1. [De nuevo.] (Http://stackoverflow.com/questions/14844864/jdbc-preparedstatement-always-returns-1-as-auto-generated-key) Deje de publicar sus conjeturas no probados aquí. – EJP

+0

Lo siento, mi error. Los he corregido. – peterong

-1
Connection connection=null; 
    int generatedkey=0; 
    PreparedStatement pstmt=connection.prepareStatement("Your insert query"); 
    ResultSet rs=pstmt.getGeneratedKeys(); 
    if (rs.next()) { 
     generatedkey=rs.getInt(1); 
       System.out.println("Auto Generated Primary Key " + generatedkey); 
    } 
Cuestiones relacionadas