Derby - Получение RETURN_GENERATED_KEYS не кажется потокобезопасным при использовании того же соединения для создания PreparedStatement

Я запускаю два вызова INSERT sql один за другим с помощью Statement.RETURN_GENERATED_KEYS, каждая вставка имеет свой собственный уникальный идентификатор, назначенный ей.

Каждый вызов генерируется с помощью connection.prepareStatement, где соединение может повторно использоваться разными потоками (пул соединений или встроенная база данных - в любом случае это одна и та же проблема).

Итак, когда я делаю:

result = preparedStatement.getGeneratedKeys();
result.next();
return result.getInt(1);

Число, которое возвращается, похоже, не является потокобезопасным!! Обычно он захватывает сгенерированный идентификатор из первого пройденного потока.

В основном, если я запускаю несколько потоков, INSERTS работает нормально, но затем, пытаясь получить автоматически сгенерированный уникальный идентификатор, он возвращает тот же идентификатор. Опять же, я подозреваю, что это связано с тем, что соединение является общим, и как я это делаю

connection.prepareStatement(sqlString, Statement.RETURN_GENERATED_KEYS);

Я вижу, что есть ряд альтернативных параметров, но я с ними не знаком. Как я могу каким-то образом гарантировать, что каждый подготовленный оператор позже вернет свой собственный уникальный автоматически сгенерированный идентификатор?

ОБНОВЛЕНИЕ: Похоже, это происходит только со встроенным драйвером базы данных derby...


person Stephane Grenier    schedule 16.02.2013    source источник


Ответы (2)


Чтобы избежать этого, вы должны закрыть PreparedStatement из:

connection.prepareStatement(sqlString, Statement.RETURN_GENERATED_KEYS);

ДО создания другого подготовленного заявления. Похоже, что в драйвере Embedded Derby может быть предположение, что код, вызывающий базу данных, по крайней мере, для INSERTS, никогда не будет многопоточным. Если вы собираетесь использовать его, НЕ используйте встроенный драйвер.

person Stephane Grenier    schedule 16.02.2013

Вы можете использовать свой собственный блок синхронизации Java вокруг ваших трех строк кода, например:

synchronized( preparedStatement )
{
    result = preparedStatement.getGeneratedKeys();
    result.next();
    return result.getInt(1);
}
person Bryan Pendleton    schedule 16.02.2013