工作上遇到了一个问题:有一个查询第三方推给我们的数据的列表页面,在查询指定项目、指定合同的数据时,后端报500的错。我看了下后端报的是
Unmatched braces for alias path
,详细原因是sql语句中有不成对的大括号。类似于:select * from student where name = '张{生'
大括号在hibernate中有特殊用途,因此会报错。
解决方案:来源于此https://blog.csdn.net/weixin_43655401/article/details/97397199
文章中提出了两种方案,第一种是参数分离,即sql语句中写占位符,然后调用setParameter
方法来传入实参,因为不符合我工作中遇到的实际问的情景,所以没有采用。
第二种是把大括号编码成别的字符,然后在sql语句中使用函数把编码后的字符解出来
比如mysql中有from_base64
方法,我们可以把{
的base64编码后的值ew==
传给它,就可以得到{
了。
即原来的查询语句:
select * from student where name = '张{生'
修改之后就变成了
select * from student where name = concat('张',from_base64('ew=='),'生')
我自己写的java的处理代码是这样的
/**
*处理查询SQL中的大括号,因为hibernate查询中会对大括号中的内容进行解析,所以如果sql语句里面有参数的实际值中包含大括号的话,可能会出现问题
* 这个方法是把所有的 使用单引号包起来的且包含给定符号的 替换成函数拼接的
* 如:
* String sql = "select * from student where name = '张{生'";
* String result = handleBrace(sql,"{");//调用该函数,消除左大括号
* 得到的reulst的值为:select * from student where name = concat('张',from_base64('ew=='),'生')
* 这样sql里面就没有左大括号了
* @param sql
* @param brace
* @return
*/
public static String handleBrace(String sql,String brace) {
int braceIndex = sql.indexOf(brace);
if (braceIndex < 0) {
return sql;
}
int leftQuoteIndex = sql.substring(0, braceIndex).lastIndexOf("'");
int rightQuoteIndex = sql.indexOf("'",braceIndex);
if (leftQuoteIndex > -1 && rightQuoteIndex > -1) {
String param = sql.substring(leftQuoteIndex, rightQuoteIndex + 1);
String newParam = StrUtil.format(" concat({}',from_base64('{}'),'{}) ",
param.substring(0, param.indexOf(brace)),
new String(Base64.getEncoder().encode(brace.getBytes(StandardCharsets.UTF_8))),
param.substring(param.indexOf(brace) + 1));
sql = sql.replace(param, newParam);
}
if (sql.indexOf(brace) > -1) {
return handleBrace(sql,brace);
}
return sql;
}