Je veux INSERT
un enregistrement dans une base de données (qui est Microsoft SQL Server dans mon cas) en utilisant JDBC en Java. En même temps, je veux obtenir l'identifiant d'insertion. Comment puis-je y parvenir en utilisant l'API JDBC?
Réponses
Trop de publicités?Si c'est un automatique de la clé générée, vous pouvez utiliser Statement#getGeneratedKeys()
pour cette. Vous avez besoin de l'appeler sur le même Statement
que celui utilisé pour l' INSERT
. Vous devez d'abord créer l'instruction à l'aide de Statement.RETURN_GENERATED_KEYS
d'aviser le pilote JDBC pour la remise des clés. Voici un exemple de base:
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.");
}
}
}
}
Notez que vous êtes à sa charge le pilote JDBC de savoir si cela fonctionne. Actuellement, la plupart des dernières versions de le faire, mais si je suis correct, Oracle JDBC driver est toujours un peu gênant avec cette. MySQL et DB2 déjà pris en charge pour les âges. PostgreSQL commencé à soutenir il court il y a. Aucun texte sur MSSQL que je n'ai jamais utilisé.
Pour Oracle, vous pouvez invoquer une CallableStatement
avec un RETURNING
clause ou un SELECT CURRVAL(sequencename)
(ou quel que soit DB-syntaxe spécifique pour le faire) directement après l' INSERT
dans la même opération pour obtenir la dernière clé générée. Voir aussi cette réponse.
Je suis frappe de Microsoft SQL Server 2008 R2 à partir d'un seul thread JDBC application basée sur le tirant vers l'arrière le dernier ID sans l'aide de la RETURN_GENERATED_KEYS des biens ou des PreparedStatement. Ressemble à quelque chose comme ceci:
private int insertQueryReturnInt(String SQLQy) {
ResultSet generatedKeys = null;
int generatedKey = -1;
try {
Statement statement = JDBCConn.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;
}
Ce blog bien isole trois principaux SQL Server "dernier" ID options: http://msjawahar.wordpress.com/2008/01/25/how-to-find-the-last-identity-value-inserted-in-the-sql-server/ - n'ai pas besoin que les deux autres encore.
Je suis à l'aide de sql server 2008, mais j'ai un développement limitation: je ne peux pas utiliser un nouveau pilote pour elle, je dois utiliser "com.microsoft.jdbc.sqlserver.SQLServerDriver" (je ne peux pas utiliser "com.microsoft.sqlserver.jdbc.SQLServerDriver").
C'est pourquoi la solution conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)
jeta un java.lang.AbstractMethodError pour moi.
Dans cette situation, une solution que j'ai trouvé est l'ancien proposée par Microsoft:
Comment Récupérer la Valeur de @@IDENTITY à l'Aide de 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)
{
}
}
}
Cette solution a fonctionné pour moi!
J'espère que cela aide!