Comment obtenir le insert ID dans JDBC?

je veux INSERT un enregistrement dans une base de données (qui est Microsoft SQL Server dans mon cas) en utilisant JDBC en Java. En même temps, je veux obtenir l'insert ID. Comment puis-je réaliser cela en utilisant L'API JDBC?

317
demandé sur Aurgho Bhattacharjee 2009-12-16 17:57:58

10 réponses

si c'est une clé générée automatiquement, vous pouvez utiliser Statement#getGeneratedKeys() pour cela. Vous devez l'appeler sur le même Statement que celui utilisé pour le INSERT . Vous avez d'abord besoin de pour créer la déclaration en utilisant Statement.RETURN_GENERATED_KEYS pour aviser le pilote JDBC de retourner les clés.

voici un exemple de base:

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.");
            }
        }
    }
}

notez que vous dépendez de la Pilote JDBC quant à savoir si cela fonctionne. Actuellement, la plupart des dernières versions fonctionneront, mais si j'ai raison, le pilote Oracle JDBC est encore un peu gênant avec cela. MySQL et DB2 l'ont déjà supporté pendant des siècles. PostgreSQL a commencé à le supporter il n'y a pas longtemps. Je ne peux pas commenter MSSQL car je ne l'ai jamais utilisé.

pour Oracle, vous pouvez invoquer un CallableStatement avec une clause RETURNING ou un SELECT CURRVAL(sequencename) (ou n'importe quelle syntaxe spécifique à la base de données pour le faire) directement après le INSERT dans la même opération pour obtenir la dernière clé générée. Voir aussi cette réponse .

564
répondu BalusC 2018-05-02 18:59:55
  1. Créer Une Colonne Générée

    String generatedColumns[] = { "ID" };
    
  2. passez cette colonne génée à votre déclaration

    PreparedStatement stmtInsert = conn.prepareStatement(insertSQL, generatedColumns);
    
  3. Utiliser ResultSet objet à aller chercher le GeneratedKeys sur l'Énoncé

    ResultSet rs = stmtInsert.getGeneratedKeys();
    
    if (rs.next()) {
        long id = rs.getLong(1);
        System.out.println("Inserted ID -" + id); // display inserted record
    }
    
9
répondu Harsh Maheswari 2017-01-16 16:10:08

je tape sur Microsoft SQL Server 2008 R2 à partir d'une application mono-threadée basée sur JDBC et je retire la dernière ID sans utiliser la propriété RETURN_GENERATED_KEYS ou toute autre déclaration préparée. Ça ressemble à ça:

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;
} 

ce billet de blog isole bien trois options de Serveur SQL "last ID" : http://msjawahar.wordpress.com/2008/01/25/how-to-find-the-last-identity-value-inserted-in-the-sql-server / - n'ont pas eu besoin les deux autres encore.

8
répondu ftexperts 2015-07-03 08:41:23

selon l'Erreur "fonction non supportée" en utilisant Statement.RETURN_GENERATED_KEYS , essayez ceci:

    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();

    }

où BRANCHID est l'id généré automatiquement

5
répondu Eitan Rimon 2015-12-14 08:39:14

j'utilise SQLServer 2008, mais j'ai une limitation de développement: Je ne peux pas utiliser un nouveau pilote pour cela, je dois utiliser" com.Microsoft.jdbc.sqlserver.SQLServerDriver" (Je ne peux pas utiliser "com.Microsoft.sqlserver.jdbc.SQLServerDriver").

C'est pourquoi la solution conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS) a lancé un java.lang.AbstractMethodError pour moi. Dans cette situation, une solution possible que J'ai trouvé est l'ancienne suggérée par Microsoft: Comment récupérer la valeur @ @ IDENTITY en utilisant 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)
        {
        }
    }
}

Cette solution a fonctionné pour moi!

j'espère que cela aidera!

3
répondu xanblax 2013-09-10 09:41:04

au lieu d'un comment , je veux juste répondre à post.


l'Interface de java.SQL.États financiers

  1. columnIndexes " vous pouvez utiliser la fonction prepareStatement qui accepte les columnIndexes et la déclaration SQL. lorsque les colonneindexes sont autorisés les drapeaux constants sont des énoncés.RETURN_GENERATED_KEYS 1 or Statement.NO_GENERATED_KEYS[2], SQL statement that may contain one or more"?"DANS les emplacements de paramètre.

    syntaxe "

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

    exemple:

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

  1. nom de la colonne " énumérez les noms de colonnes comme 'id', 'uniqueID', ... . dans la table cible qui contient les clés générées automatiquement qui doivent être retournées. Le pilote les ignorera si la déclaration SQL n'est pas une déclaration INSERT .

    syntaxe "

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

    exemple:

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

Exemple Complet:

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();
    }
}
0
répondu Yash 2018-01-18 13:20:04

avec le NativeQuery D'Hibernate, vous devez retourner une liste de résultats au lieu d'un simple résultat, parce que Hibernate modifie une requête native

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

comme

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

si vous essayez d'obtenir un seul résultat, ce qui provoque une erreur de syntaxe dans la plupart des bases de données (au moins PostgreSQL). Ensuite, vous pouvez récupérer l'id résultant de la liste (qui contient généralement un élément).

0
répondu Balin 2018-04-23 08:26:35

il est possible de l'utiliser avec normal Statement 's ainsi (pas seulement 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.");
  }
}
0
répondu rogerdpack 2018-05-04 19:33:08

dans mon cas - >

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);
}
0
répondu TheSagya 2018-08-29 13:37:58
Connection cn = DriverManager.getConnection("Host","user","pass");
Statement st = cn.createStatement("Ur Requet Sql");
int ret  = st.execute();
-5
répondu Abdelkhalek Benhoumine 2017-03-14 23:00:57