JavaのJDBCを使ってデータベース(私の場合はMicrosoft SQL Server)のレコードをINSERT
したいと思います。同時に、インサートIDを取得したいのですが。 JDBC APIを使用してこれを実現する方法を教えてください。
それが自動生成されたキーであるならば、あなたはこれのために Statement#getGeneratedKeys()
を使うことができます。 Statement
に使用されているのと同じINSERT
でそれを呼び出す必要があります。最初にneedを使用して、 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ドライバに依存していることに注意してください。現時点では、最新バージョンのほとんどが機能しますが、正しければ、Oracle JDBCドライバはまだこれに関していくらか面倒です。 MySQLとDB2はすでに長い間サポートしていました。 PostgreSQLはそれほど前にサポートし始めました。私はそれを使ったことがないので、私はMSSQLについてコメントすることができません。
Oracleの場合、最後の生成キーを取得するために、同じトランザクション内でCallableStatement
の直後にRETURNING
句またはSELECT CURRVAL(sequencename)
(またはそのためのDB固有の構文)を指定してINSERT
を呼び出すことができます。この答えも 見てください 。
生成列を作成する
String generatedColumns[] = { "ID" };
この列をあなたのステートメントに渡してください
PreparedStatement stmtInsert = conn.prepareStatement(insertSQL, generatedColumns);
Statement上のGeneratedKeysを取得するにはResultSet
オブジェクトを使用する
ResultSet rs = stmtInsert.getGeneratedKeys();
if (rs.next()) {
long id = rs.getLong(1);
System.out.println("Inserted ID -" + id); // display inserted record
}
RETURN_GENERATED_KEYSプロパティやPreparedStatementを使用せずに、シングルスレッドのJDBCベースのアプリケーションからMicrosoft SQL Server 2008 R2にアクセスし、最後の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;
}
このブログ記事では、SQL Serverの3つの主要な「ラストID」オプションを適切に分離しています。 SQL Serverに挿入/ - 他の2つはまだ必要ありません。
Statement.RETURN_GENERATED_KEYS
を使用した 'Unsupported feature'エラーに従って、これを試してください:
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は自動生成されたIDです。
私はSQLServer2008を使用していますが、開発上の制限があります。新しいドライバを使用することはできません。 "com.Microsoft.jdbc.sqlserver.SQLServerDriver"を使用する必要があります。 ( "com.Microsoft.sqlserver.jdbc.SQLServerDriver"は使用できません)。
それで、conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)
という解決策がJava.lang.AbstractMethodErrorを投げてくれたのです。この状況で、私が見つけた可能な解決策はマイクロソフトによって提案された古いものです: JDBCを使用して@@ IDENTITY値を取得する方法
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コードを使用して、新しく挿入されたIDを取得できます。
ps = con.prepareStatement(query, Statement.RETURN_GENERATED_KEYS);
ps.setInt(1, quizid);
ps.setInt(2, userid);
ps.executeUpdate();
ResultSet rs = ps.getGeneratedKeys();
if (rs.next()) {
lastInsertId = rs.getInt(1);
}
Hibernateのネイティブクエリでは、Hibernateがネイティブクエリを変更するため、SingleResultの代わりにResultListを返す必要があります。
INSERT INTO bla (a,b) VALUES (2,3) RETURNING id
好き
INSERT INTO bla (a,b) VALUES (2,3) RETURNING id LIMIT 1
単一の結果を得ようとすると、ほとんどのデータベース(少なくともPostgreSQL)で構文エラーが発生します。その後、リストから結果のIDを取得することができます(通常は正確に1つの項目を含みます)。
Spring JDBCを使用している場合は、挿入されたIDを取得するためにSpringのGeneratedKeyHolderクラスを使用できます。
この回答を見る... Spring Jdbctemplate.update(String sql、obj ... args)を使って挿入されたIDを取得する方法
私の場合 - >
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);
}
コメント の代わりに、投稿に回答したいだけです。
インタフェースJava.sql.PreparedStatement
columnIndexes"columnIndexesとSQL文を受け付けるprepareStatement関数を使用できます。columnIndexesで許可された定数フラグはStatement.RETURN_GENERATED_KEYS 1 またはStatement.NO_GENERATED_KEYS [2]、1つ以上の '?'を含むことができるSQLステートメントです。 INパラメーターのプレースホルダー。
構文"
Connection.prepareStatement(String sql, int autoGeneratedKeys)
Connection.prepareStatement(String sql, int[] columnIndexes)
例:
PreparedStatement pstmt =
conn.prepareStatement( insertSQL, Statement.RETURN_GENERATED_KEYS );
columnNames"'id', 'uniqueID', ...
のようにcolumnNamesをリストします。返されるべき自動生成キーを含むターゲットテーブル内。 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();
}
}
通常のStatement
と一緒に使うことも可能です(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.");
}
}