Відповіді:
Якщо це автоматично створений ключ, то ви можете використовувати Statement#getGeneratedKeys()
для цього. Вам потрібно викликати його так само, Statement
як і те, що використовується для INSERT
. Спочатку потрібно створити оператор, використовуючи 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, ви можете викликати CallableStatement
за допомогою RETURNING
пункту або SELECT CURRVAL(sequencename)
(або будь-який інший БД специфічного синтаксису , щоб зробити це) , безпосередньо після того , INSERT
в тій же транзакції , щоб отримати останній згенерований ключ. Дивіться також цю відповідь .
generatedKeys.next()
повертається , true
якщо DB повертається згенерований ключ. Подивіться, це а ResultSet
. Справа close()
лише у тому, щоб звільнити ресурси. Інакше у вашої БД буде вичерпано їх довгостроково, і ваша програма порушиться. Вам просто потрібно написати якийсь корисний метод самостійно, який виконує завдання закриття. Дивіться також цю і цю відповідь.
Створіть генеровану колонку
String generatedColumns[] = { "ID" };
Передайте цей сформований стовпець до вашої заяви
PreparedStatement stmtInsert = conn.prepareStatement(insertSQL, generatedColumns);
Використовуйте ResultSet
об'єкт для отримання згенерованих ключів у заяві
ResultSet rs = stmtInsert.getGeneratedKeys();
if (rs.next()) {
long id = rs.getLong(1);
System.out.println("Inserted ID -" + id); // display inserted record
}
Я натискаю на Microsoft SQL Server 2008 R2 з однопотокової програми на базі JDBC і відтягую останній ідентифікатор, не використовуючи властивість RETURN_GENERATED_KEYS або будь-який підготовлений стан. Виглядає приблизно так:
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: http://msjawahar.wordpress.com/2008/01/25/how-to-find-the-last-identity-value-inserted-in-the -sql-server / - інші два ще не потрібні.
Під час використання помилки "Непідтримувана функція" під час використання 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
автоматично створений ідентифікатор.
BATCHID
Я використовую SQLServer 2008, але у мене є обмеження в розробці: я не можу використовувати для нього новий драйвер, я повинен використовувати "com.microsoft.jdbc.sqlserver.SQLServerDriver" (я не можу використовувати "com.microsoft.sqlserver.jdbc .SQLServerDriver ").
Ось чому рішення conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)
кинуло для мене java.lang.Ab абстрактMethodError . У цій ситуації можливим рішенням, який я знайшов, є старе, запропоноване Microsoft:
Як отримати значення @@ IDENTITY за допомогою 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)
{
}
}
}
Це рішення спрацювало на мене!
Я сподіваюся, що це допомагає!
Замість коментаря я просто хочу відповісти на повідомлення.
Інтерфейс java.sql.PreparedStatement
columnIndexes «Ви можете використовувати функцію PrepaStatement, яка приймає columnIndexes і оператор SQL. Якщо постійні прапорці stolIndexes дозволені постійними прапорцями, є Statement.RETURN_GENERATED_KEYS 1 або Statement.NO_GENERATED_KEYS [2], оператор SQL, який може містити один або більше "?" IN заповнення параметрів.
SYNTAX «
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
оператором.
SYNTAX «
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();
}
}
Ви можете використовувати наступний код Java для отримання нового вставленого ідентифікатора.
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);
}
За допомогою NativeQuery Hibernate потрібно повернути 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) кидають синтаксичну помилку. Згодом ви можете отримати отриманий ідентифікатор зі списку (який зазвичай містить точно один елемент).
Можна використовувати його і з нормальними 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.");
}
}
У моєму випадку ->
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, ви можете використовувати клас GeneratedKeyHolder Spring, щоб отримати вставлений ідентифікатор.
Дивіться цю відповідь ... Як вставити ідентифікатор за допомогою 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
Метод від Connection
не очікуйте ніяких парам. 2. execute
Метод Statement
очікує рядок із запитом. 3. execute
Метод повертає: true
якщо перший результат є ResultSet
об’єктом; false
якщо це кількість оновлень або немає результатів. docs.oracle.com/javase/7/docs/api/java/sql/…
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); }