【问题标题】:SQL exception preparing query with ORMLite使用 ORMLite 准备查询的 SQL 异常
【发布时间】:2011-07-13 21:46:06
【问题描述】:

我正在使用 ORM (ORMlite) 并且我的所有调用都运行良好,直到出现以下错误。

线程“main”中的异常 org.h2.jdbc.JdbcSQLException:SQL 语句中的语法错误“ SELECT * FROM ""STORIES"" WHERE ""TITLE"" = 'Deepcut case 导致'NOT FOLLOWED[*]'' "; SQL 语句: SELECT * FROM Stories WHERE title = 'Deepcut case 导致'未遵循'' [42000-152] 在 org.h2.message.DbException.getJdbcSQLException(DbException.java:327) 在 org.h2.message.DbException.get(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.java:71) 在 org.h2.jdbc.JdbcConnection.prepareStatement(JdbcConnection.java:601) 在 com.j256.ormlite.jdbc.JdbcDatabaseConnection.compileStatement(JdbcDatabaseConnection.java:83) 在 com.j256.ormlite.stmt.mapped.MappedPreparedStmt.compile(MappedPreparedStmt.java:44) 在 com.j256.ormlite.stmt.StatementExecutor.buildIterator(StatementExecutor.java:169) 在 com.j256.ormlite.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);

【问题讨论】:

    标签: java sql exception h2 ormlite


    【解决方案1】:

    SQL 语句 "SELECT * FROM ""STORIES"" WHERE ""TITLE"" 中的语法错误...

    @bemace 是正确的,标题中似乎有引号会破坏查询生成的字符串的转义。

    在 ORMLite 中,您应该使用SelectArg 功能,该功能将使用 SQL 生成查询?参数,然后将字符串直接传递给准备好的语句。

    请参阅documentation on the 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);
    

    【讨论】:

      【解决方案2】:

      我有点猜测,但看起来title 字段中的值有问题,可能是未转义的引号?

      我不熟悉 ORMLite,但 title = 'Deepcut case leads 'not followed'' 看起来不对。应该是 "Deepcut case leads 'not followed'"'Deepcut case leads \'not followed\'' 或类似的。

      【讨论】:

      • 使用双引号或反斜杠在 H2 上不起作用,因为它遵循 SQL 标准。这意味着字符串文字需要用单引号括起来,并且要嵌入另一个引号,您需要使用两个单引号:'Deepcut case leads ''not followed'
      • 是的,根据 SQL 标准,'Deepcut case lead''not follow' 是正确的。所有 SQL 数据库都支持这一点。
      • 更多细节:'Deepcut case leads ''not followed''' 根据 SQL 标准是正确的。所有 SQL 数据库都支持这一点。 "Deepcut case leads 'not followed'" 是一个带引号的标识符,同样根据 SQL 标准(但我猜没有这样的列名)。 'Deepcut case leads \'not followed\'' 根据 SQL 标准是非法的,但如果禁用 SQL 兼容性,则 MySQL 和 PostgreSQL 支持。
      • 有没有办法让java自动转义我的字符串?还是我自己写?
      • @Alex:使用 PreparedStatement,您不必担心这样的事情
      【解决方案3】:

      该语句的正确语法是:

      SELECT * FROM Stories WHERE title = 'Deepcut case lead ''not follow'' ';

      注意字符串文字中重复的单引号。

      您需要告诉您的 ORM 层遵循 ANSI SQL 文字规则。

      【讨论】:

        【解决方案4】:

        异常表示您生成的 SELECT 语句存在一些语法问题。你能打印出生成的查询吗?这样做可能会帮助您确定此处的确切问题。

        编辑:仔细查看您的跟踪表明这里没有正确处理字符串转义。这是您自己的 QueryBuilder 吗?还有,按照this link,你是用SelectArg还是直接设置标题?

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-07-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-03-30
          • 2012-07-16
          • 1970-01-01
          相关资源
          最近更新 更多