我想在 Java 中使用 JDBC 来INSERT
数据库(在我的例子中是 Microsoft SQL Server)中的一条记录。同时,我想获取插入ID。如何使用 JDBC API 实现这一点?
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); }
中保留自动生成的 id
如果它是自动生成的密钥,那么您可以为此使用 Statement#getGeneratedKeys()
。您需要在与 INSERT
相同的 Statement
上调用它。您首先需要创建使用 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,您可以在同一事务中直接在 INSERT
之后调用带有 RETURNING
子句或 SELECT CURRVAL(sequencename)
(或任何特定于数据库的语法)的 CallableStatement
,以获取最后生成的密钥。另见this answer。
创建生成的列字符串 generatedColumns[] = { "ID" };将此生成的列传递给您的语句 PreparedStatement stmtInsert = conn.prepareStatement(insertSQL, generatedColumns);使用 ResultSet 对象获取 Statement ResultSet rs = stmtInsert.getGeneratedKeys() 上的 GeneratedKeys; if (rs.next()) { long id = rs.getLong(1); System.out.println("插入的 ID -" + id); // 显示插入的记录 }
我正在从基于 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;
}
这篇博文很好地隔离了三个主要的 SQL Server“last ID”选项:http://msjawahar.wordpress.com/2008/01/25/how-to-find-the-last-identity-value-inserted-in-the-sql-server/ - 还不需要另外两个。
statement.getGeneratedKeys()
提供 ID,这使得这种尝试“可以理解”。然而,在prepareStatement 期间提供ID 可以解决这个问题(例如preapareStatement(query, new String[] {insertIdColumnName})
)。有关更多详细信息,请参阅@Yash 略微被低估的答案。
如果在使用 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();
}
其中 BATCHID
是自动生成的 ID。
BATCHID
我只想回答帖子,而不是 comment。
columnIndexes « 您可以使用接受 columnIndexes 和 SQL 语句的 prepareStatement 函数。其中 columnIndexes 允许的常量标志是 Statement.RETURN_GENERATED_KEYS1 或 Statement.NO_GENERATED_KEYS[2],可能包含一个或多个“?”的 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”、...。如果 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();
}
}
@@IDENTIY
(当提供 String Array
个请求的 ID 时)。
我正在使用 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)
{
}
}
}
这个解决方案对我有用!
我希望这有帮助!
String[]
您想要的 ID 名称数组,而不是 RETURN_GENERATED_KEYS
。这应该会突然通过其中的 getInt(1) 为您提供一个有效的 ResultSet 和 ID。
您可以使用以下 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);
}
也可以将它与普通的 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.");
}
}
使用 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)抛出语法错误。之后,您可以从列表中获取结果 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);
}
如果您使用的是 Spring JDBC,则可以使用 Spring 的 GeneratedKeyHolder 类来获取插入的 ID。
看到这个答案... How to get inserted id using Spring Jdbctemplate.update(String sql, obj...args)
如果您使用的是 JDBC(用 MySQL 测试)并且您只想要最后插入的 ID,那么有一种简单的方法可以得到它。我正在使用的方法如下:
public static Integer insert(ConnectionImpl connection, String insertQuery){
Integer lastInsertId = -1;
try{
final PreparedStatement ps = connection.prepareStatement(insertQuery);
ps.executeUpdate(insertQuery);
final com.mysql.jdbc.PreparedStatement psFinal = (com.mysql.jdbc.PreparedStatement) ps;
lastInsertId = (int) psFinal.getLastInsertID();
connection.close();
} catch(SQLException ex){
System.err.println("Error: "+ex);
}
return lastInsertId;
}
此外,(以防万一)获取 ConnectionImpl
的方法如下:
public static ConnectionImpl getConnectionImpl(){
ConnectionImpl conexion = null;
final String dbName = "database_name";
final String dbPort = "3306";
final String dbIPAddress = "127.0.0.1";
final String connectionPath = "jdbc:mysql://"+dbIPAddress+":"+dbPort+"/"+dbName+"?autoReconnect=true&useSSL=false";
final String dbUser = "database_user";
final String dbPassword = "database_password";
try{
conexion = (ConnectionImpl) DriverManager.getConnection(connectionPath, dbUser, dbPassword);
}catch(SQLException e){
System.err.println(e);
}
return conexion;
}
请记住将 connector/J 添加到项目引用的库中。
就我而言,连接器/J 版本是 5.1.42。如果您想使用更现代的连接器/J 版本(例如版本 8.0.28),您可能必须对 connectionPath
应用一些更改。
在文件中,记得导入以下资源:
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import com.mysql.jdbc.ConnectionImpl;
希望这会有所帮助。
Connection cn = DriverManager.getConnection("Host","user","pass");
Statement st = cn.createStatement("Ur Requet Sql");
int ret = st.execute();
Connection
中的 createStatement
方法不需要任何参数。 2. Statement
中的 execute
方法需要一个带有查询的字符串。 3. execute
方法返回: true
如果第一个结果是 ResultSet
对象; false
如果是更新计数或没有结果。 docs.oracle.com/javase/7/docs/api/java/sql/…
不定期副业成功案例分享
generatedKeys.next()
返回true
。看,它是一个ResultSet
。close()
只是为了释放资源。否则,您的数据库将长期用完它们,您的应用程序将中断。你只需要自己编写一些实用方法来完成关闭任务。另请参阅 this 和 this 答案。