PostgreSQL中带有特殊字符的全文搜索异常

时间:2013-04-23 12:07:47

标签: java hibernate java-ee ejb postgresql-8.4

我试图通过搜索文本获取对象列表。如果我使用特殊字符串继续执行此操作,

searchText ="Agenya\\&\&";
像这样查询 (我正在使用Postgres的全文搜索方法)

select object from Object object where object.Id = :Id and fts('english',object.searchColumn,'Agenya\\&\&') = true  order by object.objectName asc

我得到这样的例外:

javax.ejb.EJBException: org.hibernate.exception.SQLGrammarException: could not execute query
    at org.jboss.ejb3.tx.Ejb3TxPolicy.handleExceptionInOurTx(Ejb3TxPolicy.java:63)
    at org.jboss.aspects.tx.TxPolicy.invokeInOurTx(TxPolicy.java:83)
    at org.jboss.aspects.tx.TxInterceptor$Required.invoke(TxInterceptor.java:191)
    at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
    at org.jboss.aspects.tx.TxPropagationInterceptor.invoke(TxPropagationInterceptor.java:95)
    at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
    at org.jboss.ejb3.stateless.StatelessInstanceInterceptor.invoke(StatelessInstanceInterceptor.java:62)
    at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
    at org.jboss.aspects.security.AuthenticationInterceptor.invoke(AuthenticationInterceptor.java:77)
    at org.jboss.ejb3.security.Ejb3AuthenticationInterceptor.invoke(Ejb3AuthenticationInterceptor.java:110)
    at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
    at org.jboss.ejb3.ENCPropagationInterceptor.invoke(ENCPropagationInterceptor.java:46)
    at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
    at org.jboss.ejb3.asynchronous.AsynchronousInterceptor.invoke(AsynchronousInterceptor.java:106)
    at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
    at org.jboss.ejb3.stateless.StatelessContainer.dynamicInvoke(StatelessContainer.java:304)
    at org.jboss.ejb3.remoting.IsLocalInterceptor.invokeLocal(IsLocalInterceptor.java:81)
    at org.jboss.ejb3.remoting.IsLocalInterceptor.invoke(IsLocalInterceptor.java:72)
    at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
    at org.jboss.ejb3.stateless.StatelessRemoteProxy.invoke(StatelessRemoteProxy.java:107)
    at $Proxy1152.getAllOpportunitiesBySearchText(Unknown Source)

Caused by: org.hibernate.exception.SQLGrammarException: could not execute query
    at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:67)
    at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
    at org.hibernate.loader.Loader.doList(Loader.java:2223)
    at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2104)
    at org.hibernate.loader.Loader.list(Loader.java:2099)
    at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:378)
    at org.hibernate.hql.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:338)
    at org.hibernate.engine.query.HQLQueryPlan.performList(HQLQueryPlan.java:172)
    at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1121)
    at org.hibernate.impl.QueryImpl.list(QueryImpl.java:79)

请帮我解决这个问题。

1 个答案:

答案 0 :(得分:0)

你正在运行相当过时的Postgres 8.4。此版本中standard_conforming_strings的默认设置为off

这给你带来了什么?

SHOW standard_conforming_strings;

如果得到off,字符串中的反斜杠将被视为转义字符。我不清楚问题是什么应该是一个逃避角色,什么应该是字面反斜杠。相应地消除你的字符串。

将文字反斜杠加倍,并在字符串前添加E,以便在切换后继续工作。或者切换到on。一定要先了解后果。

同时检查您的任何软件层是否也将\视为转义字符。你可能不得不再次加倍。如果有疑问,在数据库日志中使用log_statement = on的日志语句会检查Postgres实际获得的内容。

一般来说,我建议升级到Postgres的更新版本。

还有两个注释:

  • 在Postgres中,表达式如

    fts(...) = true
    
    WHERE子句中的

    始终可以简化为

    fts(...)
    
  • Identifiers are cast to lower case如果不是双引号。因此:

    from Object object
    

    实际上只是一种吵闹的说法:

    from object
    

    如果您的表名和列名在创建时实际上是双引号,则需要在其余的存在时对它们进行双引号。我的建议:远离PostgreSQL中的CaMeL案例标识符,省去麻烦。