Почему использование подготовленного оператора завершается ошибкой с нулевыми значениями и успешным с GStrings?

В двух словах о проблеме:

Вот что происходит при попытке вставить строку с несколькими пустыми столбцами с помощью подготовленного оператора и groovy.sql.Sql:

groovy:000> val
===> [123123123, 2, null, 0, 0, , null, , 1213020112511801, 1283425009158952, 1, 2, null, 0, 0, , null, , 1213020112511801, 1283425009158952]
groovy:000> destSql.execute "insert into my_table values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", val
ERROR java.sql.SQLException: Type is not supported.
        at org.apache.derby.client.am.SQLExceptionFactory40.getSQLException (Unknown Source)
        at org.apache.derby.client.am.SqlException.getSQLException (Unknown Source)
        at org.apache.derby.client.am.PreparedStatement.setObject (Unknown Source)
        at groovysh_evaluate.run (groovysh_evaluate:3)
        ...
groovy:000> 

Я получаю аналогичный результат с destSql.dataSet("my_table").add valueMap.

Вот что происходит при попытке вставить ту же строку, что и GString:

groovy:000> destSql.execute "insert into my_table values (${val[0]}, ${val[1]}, ${val[2]}, ${val[3]}, ${val[4]}, ${val[5]}, ${val[6]}, ${val[7]}, ${val[8]}, ${val[9]})"
===> false
groovy:000> 

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

Я хотел бы понять следующее:

1) Мне трудно поверить, что вставка нулей с помощью подготовленных операторов невозможна, так почему это иногда вызывает проблемы? Менее совершенные драйверы JDBC, движки баз данных?

2) Почему работает пример с GString? Следуя той же логике, он по-прежнему не набирает информацию даже о нулевых столбцах, так как же это работает?


person Tomislav Nakic-Alfirevic    schedule 25.09.2010    source источник


Ответы (2)


Вы получите лучшие ответы, если включите фактическое исключение, с которым столкнулись. Вы можете найти исключение в файле derby.log вашего сервера Derby или изменить свое приложение, чтобы распечатать всю цепочку исключений, а не только самое внешнее исключение на стороне клиента: http://wiki.apache.org/db-derby/UnwindExceptionChain

Не видя фактического исключения, вам довольно сложно помочь, но рискну предположить, что вы видите https://issues.apache.org/jira/browse/DERBY-1938

person Bryan Pendleton    schedule 25.09.2010
comment
Это была отличная ссылка, Брайан, я считаю, что она хорошо объясняет, почему проблема периодически возникает (некоторые комбинации драйвера, СУБД и шаблона использования) и почему использование подготовленного оператора не работает в моем случае. - person Tomislav Nakic-Alfirevic; 25.09.2010
comment
У вас есть идея, почему подход GStrings работает? Я бегло просмотрел исходный код groovy.sql.Sql и увидел, что он также пытается создать подготовленный оператор ... передав ему значения Object, а не String, я не могу представить, как это могло бы работать в противном случае, но дерби отклонил бы подготовленный оператор с нулевым значением ...? - person Tomislav Nakic-Alfirevic; 25.09.2010
comment
Я почти уверен, что для ряда выпусков PreparedStatement.setString (N, null) нормально работал в Derby, но PreparedStatement.setObject (N, null) не удался. Я считаю, что это была суть проблемы, которую решила DERBY-1938. Так что, возможно, в зависимости от конкретных типов данных, которые использовала ваша программа Groovy, библиотека Groovy SQL иногда вызывала setString, а иногда вызывала setObject? - person Bryan Pendleton; 26.09.2010
comment
Я бы не сказал, что это вероятная причина, но я считаю, что вы правильно ответили на другую часть загадки (почему она не работает в моем случае), поэтому я завершу ее здесь. - person Tomislav Nakic-Alfirevic; 29.09.2010

пример gstring работает, потому что код ${val[0]} вернет null, если элемент массива равен нулю.

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

person Aaron Saunders    schedule 25.09.2010
comment
Вы можете увидеть значения, которые я пытался вставить: они представляют собой действительную запись с парой полей, для которых установлено значение NULL. ${val[0]} действительно вернет null, но почему Derby принимает это и не принимает нулевое значение в качестве параметра подготовленного оператора? - person Tomislav Nakic-Alfirevic; 25.09.2010