INSERT
Java で JDBC を使用して、データベース (私の場合は Microsoft SQL Server) にレコードを作成したいと考えています。同時にインサートIDも取得したい。JDBC API を使用してこれを達成するにはどうすればよいですか?
12 に答える
自動生成されたキーの場合は、これを使用できます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
生成列の作成
String generatedColumns[] = { "ID" };
この生成された列をステートメントに渡します
PreparedStatement stmtInsert = conn.prepareStatement(insertSQL, generatedColumns);
オブジェクトを使用
ResultSet
してステートメントの GeneratedKeys を取得しますResultSet rs = stmtInsert.getGeneratedKeys(); if (rs.next()) { long id = rs.getLong(1); System.out.println("Inserted ID -" + id); // display inserted record }
シングルスレッドの 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 つはまだ必要ありません。
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)
{
}
}
}
この解決策は私にとってはうまくいきました!
これが役立つことを願っています!