Как узнать количество строк, измененных от выполнения JDBC
Я не уверен, как получить количество строк, затронутых выполнением SQL.
Я делаю так:
boolean isResultSet = statement.execute(arbitrarySQLCommand);
и я могу получить количество строк, затронутых getUpdateCount()
метод. Это все хорошо. У меня проблема, когда счетчик обновлений равен нулю. Это может означать:
Это был оператор DML, но он не влиял ни на какие строки. Нулевые строки затронуты - это правильный ответ. Я просто имею в виду, что какое-то условие не было выполнено.
Это был оператор не-DML (скорее всего, оператор DDL), который по определению не изменяет строки, поэтому счетчик обновлений всегда равен нулю (дух!). Или, другими словами: концепция количества обновлений не имеет смысла для таких утверждений.
Что я хотел бы, так это уметь различать ситуацию 1 и 2 выше. Как?
Меня не интересуют операторы, которые производят вывод, поэтому я мог бы также использовать executeUpdate(), но, как я вижу, возвращаемое значение из этого метода имеет тот же недостаток:
Возвращает:
либо (1) количество строк для операторов языка данных SQL (DML), либо (2) 0 для операторов SQL, которые ничего не возвращают
Arghhh!
Я бы хотел, чтобы это было:
Возвращает:
либо (1) количество строк для операторов языка данных SQL (DML), либо (2) -1 для операторов SQL, которые ничего не возвращают
(примечание: я не знаю содержания arbitrarySQLCommand
заранее)
Окончательно выбранное решение
Похоже, что JDBC-подобного решения проблемы не существует. На мой взгляд, дизайнеры JDBC допустили серьезную ошибку в getUpdateCount
используя значение 0 (ноль) для обозначения оператора, который (по определению) не влияет на строки, поскольку затронутый ноль строк также является абсолютно допустимым значением для результата оператора DML.
Кажется, что единственное возможное решение состоит в том, чтобы выполнить какое-либо сопоставление с шаблоном в операторе SQL, чтобы выяснить, является ли это оператором DML (INSERT,UPDATE,DELETE) или оператором SQL другого типа. Что-то вроде этого:
- Извлечь первое слово из
arbitrarySQLCommand
, Слово оканчивается пробелом или символом EOL. - Если это слово (без учета регистра) имеет значение INSERT, UPDATE или DELETE, то это оператор DML и вывод из
getUpdateCount()
актуально, в противном случае выводgetUpdateCount()
не имеет значения.
Гадкий и подверженный ошибкам. Но единственно возможное решение, которое вышло из этого ТАКОГО вопроса.:-(
2 ответа
Лучшее, что вы можете сделать, это проверить оператор SQL
Set<String> dmlCommands = new HashSet<String>() {
{
add("UPDATE"); add("INSERT"); add("DELETE"); //Add more DML commands ....
}
};
int updateCount = statement.getUpdateCount();
for(String dml : dmlCommands) {
if(arbitrarySQLCommand.toUpperCase().contains(dml) && updateCount == 0) {
updateCount = -1;
break;
}
}
Возможно, мой ответ не поможет вам с тем, что вы спросили, но я попал сюда, когда искал, как получить количество строк, на которое влияют, после запуска DML, а не числа строк - с MySQL. И я пишу здесь, что я нашел, чтобы помочь другим.
Моя проблема заключалась в том, что когда я запускаю инструкцию, которая не вносит никаких изменений в таблицу, например
UPDATE table SET field=1 WHERE field=1
метод Statement.executeUpdate(...)
возвращает количество найденных строк, а не количество измененных / затронутых строк. Поэтому я не мог сказать, изменил ли запрос что-то в таблице.
Чтобы изменить это, опция должна быть предоставлена в URL при создании соединения (с DriverManager.getConnection()
), как это:
jdbc:mysql://${jdbc.host}/${jdbc.db}?
useAffectedRows=true
Я нашел это здесь:
http://mybatis-user.963551.n3.nabble.com/Return-number-of-changed-rows-tp3888464p3903155.html
И документация MySQL:
https://dev.mysql.com/doc/connector-j/5.1/en/connector-j-reference-configuration-properties.html