マルチスレッド環境では、select ステートメントが挿入の前に発生するため、2 つのスレッドが同じ値の batch_id を参照できます。たとえば、次の処理が順番に行われていると想像してください。
Thread 1:
SELECT (MAX(batch_id) + 1) # returns 1
Thread 2:
SELECT (MAX(batch_id) + 1) # returns 1 again, nothing has changed
Thread 1:
INSERT INTO audit VALUES (1, "feedname"); # because 1 was SELECTed before
Thread 2:
INSERT INTO audit VALUES (1, "feedname"); #crash!
データベースがサポートしている場合は、シーケンスまたは自動インクリメント主キーを使用してください。
編集:OPのコメントに応じた回避策
1.次の SQL ステートメントを使用して、次の batch_id 値を Java 変数に取得し、プロセスを初期化します。
SELECT (MAX(batch_id) + 1) from audit;
2. 同期された Java メソッドを使用して、次の ID を取得します。
private synchronized int getNextBatchId() {
return nextId++;
}
3.Prepared Statements でメソッドを使用する:
PreparedStatement ps = connection.prepareStatement("INSERT INTO audit VALUES (?, 'feedname')");
ps.setInt(1, getNextBatchId());
ps.execute();