419

INSERTJava で JDBC を使用して、データベース (私の場合は Microsoft SQL Server) にレコードを作成したいと考えています。同時にインサートIDも取得したい。JDBC API を使用してこれを達成するにはどうすればよいですか?

4

12 に答える 12

715

自動生成されたキーの場合は、これを使用できますStatement#getGeneratedKeys()Statementに使用されているものと同じで呼び出す必要がありますINSERT。最初に、キーを返すように JDBC ドライバーに通知するために使用するステートメントを作成する必要があります。Statement.RETURN_GENERATED_KEYS

基本的な例を次に示します。

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 ドライバーが機能するかどうかは、JDBC ドライバーに依存していることに注意してください。現在、最新のバージョンのほとんどは動作しますが、私が正しければ、Oracle JDBC ドライバーはまだこれでやや面倒です。MySQL と DB2 は、すでに長い間サポートしていました。PostgreSQL がサポートを開始したのはつい最近のことです。MSSQL は使ったことがないのでコメントできません。

Oracle の場合、最後に生成されたキーを取得するために、同じトランザクション内の の直後に、句または a (またはそうする DB 固有の構文) をCallableStatement使用してRETURNINGを呼び出すことができます。この回答も参照してください。SELECT CURRVAL(sequencename)INSERT

于 2009-12-16T15:03:14.127 に答える
27
  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
    }
    
于 2016-12-06T04:59:53.567 に答える
9

シングルスレッドの JDBC ベースのアプリケーションから Microsoft SQL Server 2008 R2 にアクセスし、RETURN_GENERATED_KEYS プロパティや PreparedStatement を使用せずに最後の ID を取得しています。次のようになります。

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

このブログ投稿では、3 つの主要な SQL Server の「最後の ID」オプションを適切に分離しています 。 -sql-server/ - 他の 2 つはまだ必要ありません。

于 2011-06-24T05:52:21.257 に答える
3

SQLServer 2008を使用していますが、開発上の制限があります。新しいドライバーを使用できないため、"com.microsoft.jdbc.sqlserver.SQLServerDriver" を使用する必要があります ("com.microsoft.sqlserver.jdbc は使用できません) .SQLServerDriver")。

そのため、ソリューションconn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)java.lang.AbstractMethodErrorをスローしました。この状況で、私が見つけた可能な解決策は、Microsoft によって提案された古いものです: How To Retrieve @@IDENTITY Value Using 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)
        {
        }
    }
}

この解決策は私にとってはうまくいきました!

これが役立つことを願っています!

于 2013-09-10T09:41:04.470 に答える