Статьи

Groovy Sql и Oracle ‘Недопустимый индекс столбца’ SQLException

Есть некоторые незначительные потенциальные опасности, связанные с ключевым словом def Groovy. Руководства по стилю и языку для Groovy для Java-разработчиков содержат некоторые предупреждения об использовании def . В этом сообщении в блоге я продемонстрирую преимущество более явного ввода при использовании Groovy SQL с базой данных Oracle, чтобы избежать потенциального исключения SQLException « Недопустимый индекс столбца », поскольку я сталкивался с этой проблемой несколько раз.

Следующий скрипт Groovy предоставляет комментарии к таблицам базы данных Oracle, соответствующим заданной строке поиска. В этом случае действия сценария не так важны, как просмотр кода, определяющего строку запроса SQL (строки 18-21).

searchDbComments.groovy (используя def без ввода String или как String)

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#!/usr/bin/env groovy
// searchDbComments.groovy
 
this.class.classLoader.rootLoader.addURL(
   new URL("file:///C:/oraclexe/app/oracle/product/11.2.0/server/jdbc/lib/ojdbc6.jar"))
 
if (args.length < 1)
{
   println "USAGE: searchDbComments.groovy <searchString>"
   System.exit(-1)
}
 
def searchString = args[0].toUpperCase()
 
import groovy.sql.Sql
def sql = Sql.newInstance("jdbc:oracle:thin:@localhost:1521:xe", "hr", "hr",
                          "oracle.jdbc.pool.OracleDataSource")
def dbTableCommentsQry = """
SELECT table_name, table_type, comments
  FROM user_tab_comments
 WHERE UPPER(comments) LIKE '%${searchString}%'"""
 
sql.eachRow(dbTableCommentsQry)
{
   println "${it.table_name} (${it.table_type}): ${it.comments}"
}

Когда приведенный выше код выполняется, генерируется следующая ошибка:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
WARNING: Failed to execute:
SELECT table_name, table_type, comments
  FROM user_tab_comments
 WHERE UPPER(comments) LIKE '%?%' because: Invalid column index
 
Caught: java.sql.SQLException: Invalid column index
 
java.sql.SQLException: Invalid column index
    at oracle.jdbc.driver.OraclePreparedStatement.setStringInternal(OraclePreparedStatement.java:5303)
    at oracle.jdbc.driver.OraclePreparedStatement.setObjectCritical(OraclePreparedStatement.java:8323)
    at oracle.jdbc.driver.OraclePreparedStatement.setObjectInternal(OraclePreparedStatement.java:8259)
    at oracle.jdbc.driver.OraclePreparedStatement.setObjectInternal(OraclePreparedStatement.java:9012)
    at oracle.jdbc.driver.OraclePreparedStatement.setObject(OraclePreparedStatement.java:8993)
    at oracle.jdbc.driver.OraclePreparedStatementWrapper.setObject(OraclePreparedStatementWrapper.java:230)
    at searchDbComments.run(searchDbComments.groovy:23)

Адресация «недопустимого индекса столбца» SQLException проста. Одним из решений является изменение «def» в строках 18-21 на явный тип «String». Другое решение, показанное в следующем листинге кода, состоит в том, чтобы использовать ключевое слово « as » в Groovy, чтобы явно использовать «def» и dbTableCommentsQry переменная dbTableCommentsQry была напечатана как String.

searchDbComments.groovy (используется как строка)

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#!/usr/bin/env groovy
// searchDbComments.groovy
 
this.class.classLoader.rootLoader.addURL(
   new URL("file:///C:/oraclexe/app/oracle/product/11.2.0/server/jdbc/lib/ojdbc6.jar"))
 
if (args.length < 1)
{
   println "USAGE: searchDbComments.groovy <searchString>"
   System.exit(-1)
}
 
def searchString = args[0].toUpperCase()
 
import groovy.sql.Sql
def sql = Sql.newInstance("jdbc:oracle:thin:@localhost:1521:xe", "hr", "hr",
                          "oracle.jdbc.pool.OracleDataSource")
def dbTableCommentsQry = """
SELECT table_name, table_type, comments
  FROM user_tab_comments
 WHERE UPPER(comments) LIKE '%${searchString}%'""" as String
 
sql.eachRow(dbTableCommentsQry)
{
   println "${it.table_name} (${it.table_type}): ${it.comments}"
}

Использование только «def» или отсутствие «def» без типа приводит к вышеуказанной ошибке. Явное определение переменной String, используемой в запросе посредством статической типизации или использования ключевого слова « as », позволяет коду выполняться правильно. Можно использовать статическую типизацию с «def», но это считается избыточным.

В использовании « def » нет ничего плохого, но нужно быть осторожным с его применением. Гийом Лафорж писал, что «def подходит для тел методов или для определенных динамических аспектов, но для всего, что является« контрактом »(сигнатуры методов, свойства и т. Д.), Лучше использовать явные типы».