jdbc java.sql.preparedstatement дублирует строки во время вставки

У меня есть программа в scala, которая подключается к базе данных оракула с помощью ojdbc, запрашивает таблицу и пытается вставить записи из java.sql.resultSet в другую таблицу в отдельном соединении jdbc.

//conn1 to oracle: java.sql.Connection = oracle.jdbc.driver.T4CConnection@698122b2
//conn2 to another non-oracle database: java.sql.Connection = com.snowflake.client.jdbc.SnowflakeConnectionV1@6e4566f1

Моя попытка получить результаты из таблицы оракула:

val stmt1 = conn1.createStatement()
stmt1.setFetchSize(3000)
val sql1 = "select userid from nex.users"
val result = stmt1.executeQuery(sql1)

и код для попытки вставки записей из результата в отдельную базу данных и таблицу через jdbc:

val insert_sql = "insert into test.users (userid) values (?)"
val ps = conn2.prepareStatement(insert_sql)
val batchSize = 3000
var count = 0
while (result.next) {
    ps.setInt(1, result.getInt(1))
    ps.addBatch()
    count += 1
    if (count % batchSize == 0) ps.executeBatch()
}

Что меня озадачивает, так это то, что во многих примерах использования jdbc синтаксис почти такой же, но во второй таблице я вижу в 4 раза больше исходного количества строк из первой таблицы.

select userid, count(*) from test.users group by userid


1 4
2 4
3 4
4 4
5 4
6 4
etc

person tchoedak    schedule 02.09.2016    source источник
comment
Вы уверены, что таблица test.users была пустой до запуска вашего кода?   -  person copeg    schedule 02.09.2016
comment
да, я усекаю таблицу каждый раз, когда пробую что-то новое с кодом, и убеждаюсь, что в ней 0 строк   -  person tchoedak    schedule 02.09.2016
comment
извините, что спрашиваю очевидное, но если вы запустите select userid, count(*) from nex.users group by userid, будут ли идентификаторы пользователей уникальными в этой таблице?   -  person homerman    schedule 03.09.2016
comment
Привет, hsl, да, идентификаторы пользователей были уникальными. Я получил предложение от коллеги - см. ответ ниже   -  person tchoedak    schedule 09.09.2016


Ответы (2)


Да, clearBatch отсутствует.

executeBatch() в конце вызывает clearBatch(). Но нет гарантии, что в других реализациях будет точно так же.

Кроме того, при необходимости я делаю незначительное тонкое дополнение к ответу tchoedak :)

ps.executeBatch();
conn2.commit();
ps.clearBatch(); 
person Roger    schedule 08.09.2016

Проблема заключалась в том, что мне нужно было выполнять ps.clearBatch() после каждого выполнения, иначе следующая партия будет нагромождена поверх предыдущей партии. При попытке сделать это на большой таблице, для которой нужно было бы чаще вызывать executeBatch, количество повторяющихся строк было в x раз выше. Окончательный код выглядит аналогично, но с ps.clearBatch() .

val ps = conn2.prepareStatement(insert_sql)
val batchSize = 3000
var count = 0
while (result.next) {
    ps.setInt(1, result.getInt(1))
    ps.addBatch()
    count += 1
    if (count % batchSize == 0) 
        ps.executeBatch()
        ps.clearBatch()
}
person tchoedak    schedule 08.09.2016