web-dev-qa-db-ja.com

Java JDBC-複数のプリペアドステートメントの一括挿入

JDBC(Oracle)を使用して、2つのテーブルのそれぞれに約1,000行を挿入する必要があります。このようなもの:

"INSERT INTO TABLE_A (A_ID, A_NAME, A_LAST_NAME) VALUES (MY_SEQUENCE.NEXTVAL, ?, ?)";
"INSERT INTO TABLE_B (B_ID, B_DESCRIPTION) VALUES (MY_SEQUENCE.CURRVAL, ?)";

問題は、両方のテーブルが共通のシーケンスで接続されているため、ステートメントの順序が重要になることです。

テーブルが1つしかない場合は非常に簡単です。その場合、私はコードを使用しました:

String insert = "Insert into TABLE_A(A_ID, A_NAME, A_LAST_NAME) values(MY_SEQUENCE.NEXTVAL, ?, ?)";
conn.setAutoCommit(false);
PreparedStatement ps = conn.prepareStatement(insert);
for(MyObject obj : myCollection) {
    ps.setString(1, obj.getName());
    ps.setString(2, obj.getLastName());
    ps.addBatch();
}
ps.executeBatch();
conn.commit();
ps.close();

ただし、このアプローチは、1つの準備済みステートメント、つまり1つのインサートでのみ機能します。この問題の解決策をどのように提供できますか?

13
agav

あなたが試すことができます

PreparedStatement ps = conn.prepareStatement(insert, Statement.RETURN_GENERATED_KEYS);
...
ps.executeBatch();

その後

ResultSet rs = ps.getGeneratedKeys();
ps = conn.prepareStatement("INSERT INTO TABLE_B (B_ID, B_DESCRIPTION) VALUES (?, ?)");

for ( int counter =0;rs.next(); counter++ ) { 
  ps.setInt(1,rs.getInt(0));
  ps.setString(2, myCollection.get(counter).getDescription());
  ps.addBatch();
}
...
13
Clint

私があなたの問題を正しく理解している場合、他のDBの使用によりCURRVALが変更される可能性があるため、NEXTVALとCURRVALに問題がありますか?その場合は、コードを次の順序に変更できます。

currentNextVal = select NEXTVAL
INSERT into table_a with currentNextVal as the id
INSERT into table_b with the same currentNextVal 

私はあなたの問題を正しく理解しましたか?

1
IncrediApp