使用withCriteria时含撇号输入触发ArrayIndexOutOfBoundsException问题
解决Grails Criteria查询中含撇号的搜索词引发的异常问题
问题根源
你遇到的ArrayIndexOutOfBoundsException是因为查询词里的单引号(撇号)破坏了SQL字符串的语法结构。比如Bo's Place直接拼进%$query%后,会变成%Bo's Place%,数据库解析时会把Bo后面的单引号当作字符串结束标记,剩下的s Place%就成了无效语法,导致底层SQL解析器报错。
解决办法
方法1:手动转义单引号(SQL标准方式)
在把查询词拼进匹配串前,把单个单引号替换成两个单引号(SQL中用两个单引号表示一个实际的单引号)。可以加个辅助方法处理:
public static List<User> myCustomSearch(String query, List<Team> teams, List<Status> statuses) { if (!statuses) { return [] } // 辅助方法:转义查询词中的单引号 def escapeQuery = { String q -> q ? q.replace("'", "''") : '' } return withCriteria { inList('status', statuses) if (teams) { team { inList('team', teams) } } if (query) { def escapedQuery = escapeQuery(query) or { ilike('username', "%${escapedQuery}%") ilike('emailAddress', "%${escapedQuery}%") ilike('firstName', "%${escapedQuery}%") ilike('lastName', "%${escapedQuery}%") } } } }
方法2:利用参数化查询(更安全,推荐)
Grails的Criteria查询支持参数绑定,直接传递包含查询词的匹配串变量,框架会自动处理特殊字符转义,同时避免SQL注入风险:
public static List<User> myCustomSearch(String query, List<Team> teams, List<Status> statuses) { if (!statuses) { return [] } return withCriteria { inList('status', statuses) if (teams) { team { inList('team', teams) } } if (query) { def likePattern = "%${query}%" or { ilike('username', likePattern) ilike('emailAddress', likePattern) ilike('firstName', likePattern) ilike('lastName', likePattern) } } } }
这里关键是把"%$query%"改成先赋值给变量likePattern,再传递给ilike,框架会把这个变量作为参数绑定到SQL中,自动处理单引号转义。
内容的提问来源于stack exchange,提问作者Misu Kuma
相关产品推荐
相关产品推荐

