web-dev-qa-db-ja.com

準備されたステートメントから自動インクリメントIDを取得する方法はありますか

Java準備済みステートメントでクエリを使用するときに、DBクエリから自動生成キーを取得する方法はありますか。

たとえば、AutoGeneratedKeysは次のように機能します。

stmt = conn.createStatement();

stmt.executeUpdate(sql, Statement.RETURN_GENERATED_KEYS);
if(returnLastInsertId) {
    ResultSet rs = stmt.getGeneratedKeys();
    rs.next();
    auto_id = rs.getInt(1);
} 

しかしながら。準備されたステートメントで挿入を行いたい場合はどうなりますか。

String sql = "INSERT INTO table (column1, column2) values(?, ?)";
stmt = conn.prepareStatement(sql);

//this is an error
stmt.executeUpdate(Statement.RETURN_GENERATED_KEYS);
if(returnLastInsertId) {
    //this is an error since the above is an error
    ResultSet rs = stmt.getGeneratedKeys();
    rs.next();
    auto_id = rs.getInt(1);
} 

私が知らないこれを行う方法はありますか。 javadocから、PreparedStatementsは自動生成IDを返すことができないようです。

58
jW.

はい。 here を参照してください。セクション7.1.9。コードを次のように変更します。

String sql = "INSERT INTO table (column1, column2) values(?, ?)";
stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);


stmt.executeUpdate();
if(returnLastInsertId) {
   ResultSet rs = stmt.getGeneratedKeys();
    rs.next();
   auto_id = rs.getInt(1);
}
92
Yishai

いくつかの方法があり、異なるjdbcドライバーが少し異なることを処理するようです、またはまったくない場合もあります(一部は自動生成された主キーのみを提供し、他の列は提供しません)が、基本的な形式は

stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS); 

または、このフォームを使用します。

String autogenColumns[] = {"column1","column2"};
stmt = conn.prepareStatement(sql, autogenColumns)
3
nos

はい、方法があります。 Java doc。

彼らの方法は、次のようにAutoGeneratedKeys IDを渡すことです

String sql = "INSERT INTO table (column1, column2) values(?, ?)";
stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
2
jW.

私は、この問題の解決策を探しているいくつかのスレッドをサーフィンして、最終的に機能するようになった人の1人です。 jdbc:Oracle:thin:with ojdbc6.jarを使用する場合注:いずれかの方法を使用できます:(方法1)

Try{
    String yourSQL="insert into Table1(Id,Col2,Col3) values(SEQ.nextval,?,?)";
    myPrepStatement = <Connection>.prepareStatement(yourSQL, Statement.RETURN_GENERATED_KEYS);
    myPrepStatement.setInt(1, 123); 
    myPrepStatement.setInt(2, 123); 

    myPrepStatement.executeUpdate();
    ResultSet rs = getGeneratedKeys;
    if(rs.next()) {
      Java.sql.RowId rid=rs.getRowId(1); 
      //what you get is only a RowId ref, try make use of it anyway U could think of
      System.out.println(rid);
    }
} catch (SQLException e) {
  //
}

(方法2)

Try{
    String yourSQL="insert into Table1(Id,Col2,Col3) values(SEQ.nextval,?,?)";
    //IMPORTANT: here's where other threads don tell U, you need to list ALL cols 
    //mentioned in your query in the array
    myPrepStatement = <Connection>.prepareStatement(yourSQL, new String[]{"Id","Col2","Col3"});
    myPrepStatement.setInt(1, 123); 
    myPrepStatement.setInt(2, 123); 
    myPrepStatement.executeUpdate();
    ResultSet rs = getGeneratedKeys;
    if(rs.next()) {
    //In this exp, the autoKey val is in 1st col
    int id=rs.getLong(1);
    //now this's a real value of col Id
    System.out.println(id);
    }
} catch (SQLException e) {
  //
}

基本的に、SEQ.Nextvalの値だけが必要な場合はMethod1を使用しないでください。RowIDrefを返すだけなので、それを使用する方法を見つけるために頭を割ることができます。それに!これは、MySQL、DB2では正常に機能する(実際のvalを返す)場合がありますが、Oracleでは機能しません。

また、デバッグ時に、SQL Developer、Toad、または同じログインセッションを使用してINSERTを実行するクライアントをオフにします。毎回(デバッグコール)影響しない場合があります...しばらく例外なくアプリがフリーズするまで。はい...例外なく停止します!

2
peterong