Yanıtlar:
Otomatik olarak oluşturulan bir anahtarsa, Statement#getGeneratedKeys()
bunun için kullanabilirsiniz . Aynı üzerine demen gerekiyor Statement
biri için kullanılan olarak INSERT
. İlk olarak , anahtarları döndürmesi için JDBC sürücüsünü bilgilendirmek için kullanarak deyimi oluşturmanız gerekirStatement.RETURN_GENERATED_KEYS
.
İşte temel bir örnek:
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 sürücüsünün çalışıp çalışmadığına bağlı olduğunuza dikkat edin. Şu anda, son sürümlerin çoğu işe yarayacak, ancak doğruysam Oracle JDBC sürücüsü bu konuda hala biraz zahmetli. MySQL ve DB2 zaten yıllardır destekliyordu. PostgreSQL uzun zaman önce desteklemeye başladı. Daha önce hiç kullanmadığım için MSSQL hakkında yorum yapamam.
Oracle için, son oluşturulan anahtarı elde etmek üzere aynı işlemden hemen sonra CallableStatement
bir RETURNING
cümle veya bir SELECT CURRVAL(sequencename)
(veya DB'ye özgü herhangi bir sözdizimi) içeren bir çağrı çağırabilirsiniz INSERT
. Ayrıca bu cevaba bakınız .
generatedKeys.next()
Döner true
DB eğer oluşturulmuş bir anahtar döndü. Bak, bu bir ResultSet
. close()
Bedava kaynaklara etmektir. Aksi takdirde DB'niz uzun vadede tükenir ve uygulamanız bozulur. Sadece kapanış görevini yapan bazı yarar yöntemlerini kendiniz yazmanız gerekir. Ayrıca bu ve bu cevaba bakınız.
Oluşturulan Sütun Oluştur
String generatedColumns[] = { "ID" };
Bu oluşturulmuş Sütunu ifadenize iletin
PreparedStatement stmtInsert = conn.prepareStatement(insertSQL, generatedColumns);
ResultSet
Deyimde GeneratedKeys getirmek için nesne kullanın
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 tek iş parçacıklı JDBC tabanlı bir uygulamadan vuruyorum ve RETURN_GENERATED_KEYS özelliğini veya herhangi bir PreparedStatement kullanmadan son kimliği geri çekiyorum. Şuna benzer bir şey var:
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;
}
Bu blog gönderisi üç ana SQL Server "last ID" seçeneğini güzel bir şekilde izole ediyor: http://msjawahar.wordpress.com/2008/01/25/how-to-find-the-last-identity-value-inserted-in-the -sql-server / - diğer ikisine henüz ihtiyaç duymadım.
Kullanırken bir 'Desteklenmeyen özellik' hatasıyla karşılaştığınızda şunu Statement.RETURN_GENERATED_KEYS
deneyin:
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
Otomatik oluşturulan kimlik nerede .
BATCHID
SQLServer 2008 kullanıyorum , ancak bir geliştirme sınırlaması var: Bunun için yeni bir sürücü kullanamıyorum, "com.microsoft.jdbc.sqlserver.SQLServerDriver" ("kullanamam" com.microsoft.sqlserver.jdbc kullanmak zorundayım) .SQLServerDriver ").
Bu yüzden çözüm benim için conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)
bir java.lang.AbstractMethodError attı . Bu durumda, bulduğum olası bir çözüm Microsoft tarafından önerilen eski çözümdür:
JDBC Kullanarak @@ IDENTITY Değerini Alma
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)
{
}
}
}
Bu çözüm benim için çalıştı!
Umarım bu yardımcı olur!
Bir yorum yerine, sadece gönderiyi cevaplamak istiyorum.
Java.sql.PreparedStatement arabirimi
columnIndexes «columnIndexes ve SQL deyimini kabul eden preparStatement işlevini kullanabilirsiniz. ColumnIndexes tarafından izin verilen sabit bayraklar Statement.RETURN_GENERATED_KEYS 1 veya Statement.NO_GENERATED_KEYS [2], bir veya daha fazla '' içerebilecek SQL ifadesi '?' IN parametre yer tutucuları.
SYNTAX «
Connection.prepareStatement(String sql, int autoGeneratedKeys)
Connection.prepareStatement(String sql, int[] columnIndexes)
Misal:
PreparedStatement pstmt =
conn.prepareStatement( insertSQL, Statement.RETURN_GENERATED_KEYS );
columnNames « Sütun adını benzer şekilde listeleyin 'id', 'uniqueID', ...
. Hedef tabloda, döndürülmesi gereken otomatik oluşturulan anahtarları içerir. SQL deyimi bir INSERT
deyim değilse sürücü bunları yoksayar .
SYNTAX «
Connection.prepareStatement(String sql, String[] columnNames)
Misal:
String columnNames[] = new String[] { "id" };
PreparedStatement pstmt = conn.prepareStatement( insertSQL, columnNames );
Tam Örnek:
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();
}
}
Yeni eklenen kimliği almak için aşağıdaki java kodunu kullanabilirsiniz.
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'in NativeQuery ile, Hibernate yerel bir sorguyu değiştirdiğinden, SingleResult yerine ResultList döndürmeniz gerekir
INSERT INTO bla (a,b) VALUES (2,3) RETURNING id
sevmek
INSERT INTO bla (a,b) VALUES (2,3) RETURNING id LIMIT 1
tek bir sonuç almaya çalışırsanız, çoğu veritabanının (en azından PostgreSQL) bir sözdizimi hatası atmasına neden olur. Daha sonra, elde edilen kimliği listeden alabilirsiniz (genellikle tam olarak bir öğe içerir).
Normal ile de kullanmak mümkündür Statement
(sadece 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.");
}
}
Benim durumumda ->
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 kullanıyorsanız, eklenen kimliği almak için Spring'in GeneratedKeyHolder sınıfını kullanabilirsiniz.
Bu yanıta bakın ... Spring Jdbctemplate.update (String sql, obj ... args) kullanarak eklenen kimlik nasıl edinilir
Connection cn = DriverManager.getConnection("Host","user","pass");
Statement st = cn.createStatement("Ur Requet Sql");
int ret = st.execute();
createStatement
yöntemi Connection
herhangi bir parametre beklemeyin. 2. execute
den gelen yöntem Statement
bir Sorgu ile bir Dize bekler. 3. execute
Yöntem döndürür: true
ilk sonuç bir ResultSet
nesne ise; false
güncelleme sayısı ise veya sonuç yoksa. 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.
;if (generatedKeys.next()) primkey = generatedKeys.getInt(1); }