2012-01-09 2 views
2

Итак, я использую Java с Apache Derby, и я пытаюсь вставить запись, но только если запись с тем же ключом еще не существует, потому что все значения, которые я хочу, чтобы существовать в моем коде, а не в базе данных я использую derbys фиктивный таблицу (аналог DUAL для db2) это запрос я использую (md5 это первичный ключ)Использование WHERE NOT EXISTS с таблицей фиктивной таблицы, не работающей с базой данных Apache Derby

PreparedStatement stmt = conn.prepareStatement("INSERT INTO artwork (md5,image) " + 
       "SELECT ?,?" + 
       "FROM SYSIBM.SYSDUMMY1 " + 
       "WHERE NOT EXISTS (SELECT 1 FROM artwork WHERE md5=?)"); 

    stmt.setString(1, key); 
    stmt.setBinaryStream(2, new ByteArrayInputStream(imageData), imageData.length); 
    stmt.setString(3, key); 

и казалось, что он работает, однако, когда я многопоточно переписываю код, чтобы два потока могли пытаться вставить те же произведения, я получаю ошибки получения ввода двойного значения в индекс.

Если я синхронизирую метод, так что только один поток может вызвать метод одновременно, то я не получаю таких ошибок, но это побеждает цель добавления значения WHERE NOT EXISTS.

Так что мой запрос не делает то, что я думаю, что он делает, или я не понимаю общую концепцию здесь?

+0

Вы пытались использовать транзакции? – Romain

+0

Не видите, как это связано –

+0

Я не вижу, как транзакции помогут в этой ситуации. К OP: есть ли что-то неправильное, просто допуская ошибки повторяющихся значений и игнорируя их? Это будет сделано с той же целью. – ean5533

ответ

0

INFO: Это решение не работает. См. Комментарии для деталей. Я оставил его здесь, чтобы кто-нибудь искал решение, которое тоже не должно пытаться это сделать.

У меня еще не было промблемы, но я бы предположил, что вы можете обойти его, если вы оптимизируете подзапрос. Нравится (это я не проверял, возможно, нуждается в улучшении):

PreparedStatement stmt = conn.prepareStatement("INSERT INTO artwork (md5,image) " + 
      "SELECT ?,?" + 
      "FROM SYSIBM.SYSDUMMY1 left join artwork exi on ? = md5" + 
      "WHERE exi.md5 IS NULL"); 

stmt.setString(1, key); 
stmt.setBinaryStream(2, new ByteArrayInputStream(imageData), imageData.length); 
stmt.setString(3, key); 
+0

Привет, спасибо, просто попробовал, и он не работал. Я думаю, что если бы я понял комментарии выше, проблема заключалась не в использовании подзапроса, а в использовании запроса для подачи данных во вставку, а anothe thread может добавить в строку между первым потоком, выполняющим SELECT и выполняющим INSERT на SELECT. –

+0

@ user294896 Вы правы, у него есть та же проблема, что и исходный запрос. – soulcheck

+0

@ user294896 Хорошо, я отредактировал сообщение в своем ответе, чтобы пометить этот ответ как неработающий. –