Câu trả lời:
Nếu đó là một khóa được tạo tự động, thì bạn có thể sử dụng Statement#getGeneratedKeys()
cho việc này. Bạn cần gọi nó giống Statement
như cái đang được sử dụng cho INSERT
. Trước tiên bạn cần tạo câu lệnh bằng cách sử dụng Statement.RETURN_GENERATED_KEYS
để thông báo cho trình điều khiển JDBC để trả về các khóa.
Đây là một ví dụ cơ bản:
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.");
}
}
}
}
Lưu ý rằng bạn phụ thuộc vào trình điều khiển JDBC xem nó có hoạt động không. Hiện tại, hầu hết các phiên bản cuối cùng sẽ hoạt động, nhưng nếu tôi chính xác, trình điều khiển JDBC của Oracle vẫn hơi rắc rối với điều này. MySQL và DB2 đã hỗ trợ nó từ lâu. PostgreSQL bắt đầu hỗ trợ nó cách đây không lâu. Tôi không thể nhận xét về MSSQL vì tôi chưa bao giờ sử dụng nó.
Đối với Oracle, bạn có thể gọi một CallableStatement
với một RETURNING
khoản hoặc một SELECT CURRVAL(sequencename)
(hoặc bất kỳ DB cụ thể cú pháp để làm như vậy) ngay sau INSERT
trong cùng một giao dịch để có được chìa khóa tạo ra cuối cùng. Xem thêm câu trả lời này .
generatedKeys.next()
về true
nếu DB trả về một khóa được tạo. Hãy nhìn xem, đó là một ResultSet
. Đây close()
chỉ là tài nguyên miễn phí. Nếu không, DB của bạn sẽ hết chúng trong thời gian dài và ứng dụng của bạn sẽ bị hỏng. Bạn chỉ cần tự viết ra một số phương thức tiện ích để thực hiện nhiệm vụ đóng. Xem thêm này và này câu trả lời.
Tạo cột được tạo
String generatedColumns[] = { "ID" };
Vượt qua cột bị biến đổi này để tuyên bố của bạn
PreparedStatement stmtInsert = conn.prepareStatement(insertSQL, generatedColumns);
Sử dụng ResultSet
đối tượng để tìm nạp GeneratedKeys trên Statement
ResultSet rs = stmtInsert.getGeneratedKeys();
if (rs.next()) {
long id = rs.getLong(1);
System.out.println("Inserted ID -" + id); // display inserted record
}
Tôi đang nhấn Microsoft SQL Server 2008 R2 từ một ứng dụng dựa trên JDBC đơn luồng và lấy lại ID cuối cùng mà không sử dụng thuộc tính RETURN_GENERATED_KEYS hoặc bất kỳ PreparedStatement nào. Trông giống như thế này:
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;
}
Bài đăng trên blog này cách ly độc đáo ba tùy chọn "ID cuối cùng" của SQL Server: http://msjawahar.wordpress.com/2008/01/11/how-to-find-the-last-identity-value-inserted-in-the -sql-server / - chưa cần hai cái kia.
Khi gặp lỗi 'Tính năng không được hỗ trợ' trong khi sử dụng Statement.RETURN_GENERATED_KEYS
, hãy thử điều này:
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();
}
Trong trường hợp BATCHID
là tự động tạo id.
BATCHID
Tôi đang sử dụng SQLServer 2008, nhưng tôi có một hạn chế phát triển: Tôi không thể sử dụng trình điều khiển mới cho nó, tôi phải sử dụng "com.microsoft.jdbc.sqlserver.SQLServerDriver" (Tôi không thể sử dụng "com.microsoft.sqlserver.jdbc .QueryServerDriver ").
Đó là lý do tại sao giải pháp conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)
đã ném java.lang.Ab tríchMethodError cho tôi. Trong tình huống này, một giải pháp khả thi mà tôi tìm thấy là giải pháp cũ được đề xuất bởi Microsoft:
Cách truy xuất @@ IDENTITY Giá trị bằng cách sử dụng 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)
{
}
}
}
Giải pháp này đã làm việc cho tôi!
Tôi hi vọng cái này giúp được!
Thay vì một bình luận , tôi chỉ muốn trả lời bài viết.
Giao diện java.sql.PreparedStatement
cột Indexes «Bạn có thể sử dụng hàm readyStatement chấp nhận cột Index và câu lệnh SQL. Trong đó các cột chỉ số cho phép các cờ không đổi được cho phép là Statement.RETURN_GENERATED_KEYS 1 hoặc Statement.NO_GENERATED_KEYS [2], câu lệnh SQL có thể chứa một hoặc nhiều '?' IN giữ chỗ tham số.
ĐỒNG HỒ
Connection.prepareStatement(String sql, int autoGeneratedKeys)
Connection.prepareStatement(String sql, int[] columnIndexes)
Thí dụ:
PreparedStatement pstmt =
conn.prepareStatement( insertSQL, Statement.RETURN_GENERATED_KEYS );
cộtNames « Liệt kê các cộtNames như thế nào 'id', 'uniqueID', ...
. trong bảng đích chứa các khóa được tạo tự động sẽ được trả về. Trình điều khiển sẽ bỏ qua chúng nếu câu lệnh SQL không phải là một INSERT
câu lệnh.
ĐỒNG HỒ
Connection.prepareStatement(String sql, String[] columnNames)
Thí dụ:
String columnNames[] = new String[] { "id" };
PreparedStatement pstmt = conn.prepareStatement( insertSQL, columnNames );
Ví dụ đầy đủ:
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();
}
}
Bạn có thể sử dụng mã java sau để có id mới được chèn.
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);
}
Với NativeQuery của Hibernate, bạn cần trả về Danh sách kết quả thay vì SingleResult, vì Hibernate sửa đổi truy vấn gốc
INSERT INTO bla (a,b) VALUES (2,3) RETURNING id
giống
INSERT INTO bla (a,b) VALUES (2,3) RETURNING id LIMIT 1
nếu bạn cố gắng để có được một kết quả duy nhất, điều này khiến hầu hết các cơ sở dữ liệu (ít nhất là PostgreSQL) gặp lỗi cú pháp. Sau đó, bạn có thể tìm nạp id kết quả từ danh sách (thường chứa chính xác một mục).
Cũng có thể sử dụng nó với bình thường Statement
(không chỉ 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.");
}
}
Trong trường hợp của tôi ->
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);
}
Nếu bạn đang sử dụng Spring JDBC, bạn có thể sử dụng lớp GeneratedKeyHolder của Spring để lấy ID được chèn.
Xem câu trả lời này ... Cách nhận id được chèn bằng Spring Jdbctemplate.update (String sql, obj ... args)
Connection cn = DriverManager.getConnection("Host","user","pass");
Statement st = cn.createStatement("Ur Requet Sql");
int ret = st.execute();
createStatement
Phương pháp từ Connection
không mong đợi bất kỳ params. 2. execute
Phương thức từ Statement
mong đợi một Chuỗi với Truy vấn. 3. execute
Phương thức trả về: true
nếu kết quả đầu tiên là một ResultSet
đối tượng; false
nếu nó là một số cập nhật hoặc không có kết quả. docs.oracle.com/javase/7/docs/api/java/sql/ Kẻ
String sql = "INSERT INTO 'yash'.'mytable' ('name') VALUES (?)"; int primkey = 0 ; PreparedStatement pstmt = con.prepareStatement(sql, new String[] { "id" }/*Statement.RETURN_GENERATED_KEYS*/); pstmt.setString(1, name); if (pstmt.executeUpdate() > 0) { java.sql.ResultSet generatedKeys = pstmt.
getGeneratedKeys ();if (generatedKeys.next()) primkey = generatedKeys.getInt(1); }