Как получить идентификатор вставки в JDBC?



Я хочу INSERT запись в базе данных (которая является Microsoft SQL Server в моем случае) с помощью JDBC в Java. В то же время, я хочу получить идентификатор вставки. Как я могу достичь этого с помощью JDBC API?

950   10  

10 ответов:

если это автоматически сгенерированный ключ, то вы можете использовать Statement#getGeneratedKeys() для этого. Вам нужно вызвать его на том же Statement как тот, который используется для INSERT. Ты первый нужно чтобы создать оператор с помощью Statement.RETURN_GENERATED_KEYS чтобы уведомить драйвер JDBC о возврате ключей.

вот простой пример:

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

обратите внимание, что вы зависите от драйвера JDBC относительно того, работает ли он. В настоящее время большинство последних версий будут работа, но если я прав, драйвер Oracle JDBC по-прежнему несколько хлопотно с этим. MySQL и DB2 уже поддерживали его на протяжении веков. PostgreSQL начал поддерживать его не так давно. Я не могу комментировать MSSQL, поскольку я никогда не использовал его.

для Oracle, вы можете вызвать CallableStatement С RETURNING пункт или SELECT CURRVAL(sequencename) (или любой другой синтаксис, специфичный для БД) непосредственно после INSERT в одной транзакции, чтобы получить последний сгенерированный ключ. Смотрите также этот ответ.

  1. Создать Созданный Столбец

    String generatedColumns[] = { "ID" };
    
  2. передайте этот генетический столбец в ваше заявление

    PreparedStatement stmtInsert = conn.prepareStatement(insertSQL, generatedColumns);
    
  3. использовать ResultSet объект для извлечения GeneratedKeys на Оператор

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

Я нажимаю Microsoft SQL Server 2008 R2 из однопоточного приложения на основе JDBC и возвращаю последний идентификатор без использования свойства RETURN_GENERATED_KEYS или любого PreparedStatement. Выглядит примерно так:

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

это сообщение в блоге красиво изолирует три основных параметра SQL Server " последний идентификатор: http://msjawahar.wordpress.com/2008/01/25/how-to-find-the-last-identity-value-inserted-in-the-sql-server/

согласно ошибке "неподдерживаемая функция" с использованием Statement.RETURN_GENERATED_KEYS, попробуйте это:

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

    }

где BRANCHID-это автоматически сгенерированный идентификатор

Я использую SQLServer 2008, но у меня есть ограничение развития: я не могу использовать новый драйвер для него, я должен использовать "com.Microsoft.интерфейс jdbc.от SQLServer.SQLServerDriver " (я не могу использовать "com.Microsoft.от SQLServer.интерфейс jdbc.SQLServerDriver").

вот почему решение conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS) бросил a java.ленг.AbstractMethodError для меня. В этой ситуации возможным решением, которое я нашел, является старое, предложенное Microsoft: как получить значение @ @ IDENTITY с помощью 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)
        {
        }
    }
}

это решение работает для меня!

надеюсь, это поможет!

вместо комментарий, Я просто хочу ответить на пост.


интерфейс java.язык SQL.PreparedStatement

  1. columnIndexes " вы можете использовать функцию prepareStatement, которая принимает columnIndexes и инструкцию SQL. где columnIndexes разрешенные постоянные флаги-это оператор.RETURN_GENERATED_KEYS1 or Statement. NO_GENERATED_KEYS[2], SQL заявление, которое может содержать один или более '? В местозаполнителей.

    синтаксис "

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

    пример:

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

  1. columnNames"список из columnNames как 'id', 'uniqueID', .... в целевой таблице, содержащей автоматически сгенерированные ключи, которые должны быть возвращены. Драйвер будет игнорировать их, если оператор SQL не является INSERT заявление.

    синтаксис "

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

    пример:

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

Полный Пример:

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

С помощью Hibernate NativeQuery вам нужно вернуть ResultList вместо SingleResult, потому что Hibernate изменяет собственный запрос

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

как

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

Если вы пытаетесь получить один результат, который вызывает большинство баз данных (по крайней мере, PostgreSQL), чтобы бросить синтаксическая ошибка. После этого вы можете забрать полученный код из списка (который обычно содержит ровно один элемент).

можно использовать его с нормальной Statement ' s также (не только 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.");
  }
}

в моем случае ->

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);
}
Connection cn = DriverManager.getConnection("Host","user","pass");
Statement st = cn.createStatement("Ur Requet Sql");
int ret  = st.execute();

Comments

    Ничего не найдено.