Исключение SQL при подготовке запроса с ORMLite

Я использую ORM (ORMlite), и все мои вызовы работают нормально, пока я не получу следующую ошибку.

Исключение в потоке "main" org.h2.jdbc.JdbcSQLException: синтаксическая ошибка в операторе SQL "SELECT * FROM" "STORIES" "WHERE" "TITLE" "" = 'Глубокий регистр приводит' NOT FOLLOWED [*] '' "; Оператор SQL: SELECT * FROM Stories WHERE title = 'Deepcut приводит к' не отслеживается '' [42000-152] в org.h2.message.DbException.getJdbcSQLException (DbException.java:327) в org.h2.message.DbException. получить (DbException.java:167) в org.h2.message.DbException.get (DbException.java:144) в org.h2.message.DbException.getSyntaxError (DbException.java:179) в org.h2.command.Parser .getSyntaxError (Parser.java:480) на org.h2.command.Parser.prepareCommand (Parser.java:229) на org.h2.engine.Session.prepareLocal (Session.java:426) на org.h2.engine. Session.prepareCommand (Session.java:374) в org.h2.jdbc.JdbcConnection.prepareCommand (JdbcConnection.java:1093) в org.h2.jdbc.JdbcPreparedStatement. (JdbcPreparedStatement.jgc:71) в JdbcConnection.prepareStatement (JdbcConnection.java:601) в com.j256.ormlite.jdbc.JdbcDatabaseConnection.compileStatement (JdbcDatabaseConnection.j ava: 83) на com.j256.ormlite.stmt.mapped.MappedPreparedStmt.compile (MappedPreparedStmt.java:44) в com.j256.ormlite.stmt.StatementExecutor.buildIterator (StatementExecutor.java:169orml) на com.j25 .stmt.StatementExecutor.query (StatementExecutor.java:119) в com.j256.ormlite.dao.BaseDaoImpl.query (BaseDaoImpl.java:189)

Я не понимаю, что идет не так. Я вызываю поиск из этих строк:

// get our query builder from the DAO
QueryBuilder<Story, Integer> queryBuilder = StoryDao.queryBuilder();
// the 'title' field must be equal to title (a variable)
queryBuilder.where().eq(Story.TITLE_FIELD_NAME, title);
// prepare our sql statement
PreparedQuery<Story> preparedQuery = queryBuilder.prepare();
// query for all stories that have that title
List<Story> accountList = StoryDao.query(preparedQuery);

person Alex    schedule 12.03.2011    source источник


Ответы (4)


Синтаксическая ошибка в операторе SQL SELECT * FROM STORIES WHERE TITLE ...

@bemace правильно, что, похоже, в заголовке есть кавычки, которые мешают экранированию строк, сгенерированных запросом.

В ORMLite вы должны использовать функцию SelectArg, которая будет генерировать запрос с помощью SQL? arguments, а затем передайте строку непосредственно в подготовленный оператор.

См. Документацию на SelectArg. С его помощью вы бы сделали что-то вроде:

QueryBuilder<Story, Integer> queryBuilder = StoryDao.queryBuilder();
SelectArg titleArg = new SelectArg();
queryBuilder.where().eq(Story.TITLE_FIELD_NAME, titleArg);
PreparedQuery<Story> preparedQuery = queryBuilder.prepare();
titleArg.setValue(title);
List<Story> accountList = StoryDao.query(preparedQuery);
person Gray    schedule 12.03.2011

Я как бы догадываюсь, но похоже, что есть проблема со значением в поле title, может быть, неэкранированная кавычка?

Я не знаком с ORMLite, но title = 'Deepcut case leads 'not followed'' выглядит неправильно. Вероятно, должно быть "Deepcut case leads 'not followed'" или 'Deepcut case leads \'not followed\'' или что-то в этом роде.

person Brad Mace    schedule 12.03.2011
comment
Использование двойных кавычек или обратной косой черты не будет работать в H2, поскольку это соответствует стандарту SQL. Это означает, что строковые литералы необходимо заключать в одинарные кавычки, а для вставки другой кавычки необходимо использовать две одинарные кавычки: 'Deepcut case leads ''not followed' - person a_horse_with_no_name; 12.03.2011
comment
Да, фраза «Deepcut ведет» «не отслеживается» является правильной в соответствии со стандартом SQL. Все базы данных SQL поддерживают это. - person Thomas Mueller; 12.03.2011
comment
Подробнее: 'Deepcut case leads ''not followed''' соответствует стандарту SQL. Все базы данных SQL поддерживают это. "Deepcut case leads 'not followed'" - это идентификатор в кавычках, опять же согласно стандарту SQL (но я предполагаю, что такого имени столбца нет). 'Deepcut case leads \'not followed\'' является недопустимым в соответствии со стандартом SQL, но поддерживается MySQL и PostgreSQL, если совместимость с SQL отключена. - person Thomas Mueller; 12.03.2011
comment
Есть ли способ заставить Java автоматически экранировать мои строки? или мне самому написать? - person Alex; 12.03.2011
comment
@Alex: используйте PreparedStatement, и вам не нужно беспокоиться о подобных вещах - person a_horse_with_no_name; 12.03.2011

Правильный синтаксис оператора:

SELECT * FROM Stories WHERE title = 'Deepcut case leads ''not followed'' ';

Обратите внимание на дублированные одинарные кавычки внутри строкового литерала.

Вам нужно будет указать вашему уровню ORM следовать правилам ANSI SQL для литералов.

person a_horse_with_no_name    schedule 12.03.2011

Исключение говорит о синтаксической проблеме с вашим сгенерированным оператором SELECT. Можете ли вы распечатать сгенерированный запрос? Это может помочь вам определить точную проблему здесь.

РЕДАКТИРОВАТЬ: пристальный взгляд на вашу трассировку показывает, что экранирование строки здесь не обрабатывается должным образом. Это ваш собственный QueryBuilder? Кроме того, согласно этой ссылке, используете ли вы SelectArg или прямо устанавливая заголовок?

person Sanjay T. Sharma    schedule 12.03.2011