A prepared statement is generated from a nonconstant String 问题的解决

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了A prepared statement is generated from a nonconstant String 问题的解决相关的知识,希望对你有一定的参考价值。

我们在DAO层经常需要按照条件来拼SQL语句,所以很难直接定义一个final的String 的SQL语句,如果这样SONARQUBE就会报A prepared statement is generated from a nonconstant String这个错误,不知道对于这种按照条件拼接SQL语句的情况如何避免出现上诉SONARQUBE错误,谢谢大家!
for example:
fina string sql = "select * from users where userid=?";
...
StringBuilder sb = new StringBuilder(sql);
if(!"".equals(userName))
sb.append(" and userName=?");


if(!"".equals(email))
sb.append(" and email=?");


...
pstmt = con.prepareStatement(sb.toString());
pstmt.setLong(1,userId);
pstmt.setString(2, userName);
pstmt.setString(3,email);
.....

这种情况pstmt = con.prepareStatement(sb.toString())就会报上面的错误了!

StringBuilder是可变对象,这里直接使用String拼接就行了吧,不用 finnal String,用String拼接,编译器会优化字符串的“+”,即使没有优化,在这种没有循环的地方,性能的损失也可以忽略不计,相反,使用“+”更适合人类的习惯,提升代码可读性。追问

sonarqube建议SQL不要使用STRING常量,而最好使用Final String,否则也会报一个错误。

追答

这么高端。。。报什么错?个人觉得你用StringBuilder或者String就很好了,莫非真的要一次性拼一个final String 出来?这也太刻板了吧

参考技术A 把你的拼的sql粘出来一个看看吧。
看你的语句第一个参数应该是userid才对。
对于这样的拼写方式,你需要判断有几个'?',然后才能写pstmt.setString();。
一般这样不定的sql拼写,用Statemenet比较好,
for example:
fina string sql = "select * from users where userid="+userid;

StringBuilder sb = new StringBuilder(sql);
if(!"".equals(userName))
sb.append(" and userName='"+userName+"'");


if(!"".equals(email))
sb.append(" and email='"+usemail'");

Statement stmt= conn.createStatement(sb.toString());
这样就不会出现你遇到的情况了追问

这种方式会报多个SONARQUBE的错误,因为直接拼SQL而不采用pstmt.set***传参的方式会有被注入的风险。

追答

报错的原因是问号的个数和pstmt.setString的个数对不上。
要是非用PreStatement的话,你就的判断查询条件中有几个问号,再按照问号的顺序去判断pstmt.setString方法里第一个参数的值。保证问号和参数的值对应上,就不会报错了。

追问

不是的,我们的代码是正常运行的,后来因为需要改SONARQUBE的问题所以就发现了上面的问题,而非?和参数的个数不匹配导致的。按照你的方式会先报有被注入风险的错误的!

参考技术B 将参数以list存储 然后遍历list放值
String sql="......";
if (StringUtils.isNotBlank(xxx)
sql += " and xxx= ? " ;
paraList.add(xxx);

....
PreparedStatement pstmt = conn.prepareStatement(sql);
for (int i = 0; i < paraList.size(); i++)
pstmt.setObject(i+1, paraList.get(i));

ResultSet rs = pstmt.executeQuery();

以上是关于A prepared statement is generated from a nonconstant String 问题的解决的主要内容,如果未能解决你的问题,请参考以下文章

函数序列错误,SQL state S1010 while execution a Prepared Statement

cannot insert multiple commands into a prepared statement问题原因及解决办法

Prepared SQL Statement Syntax

使用 Prepared Statement 设置 LONG 数据类型

当 Statement 与 Java 和 Oracle 一起使用时,Prepared Statement 不起作用

MYSQLI Prepared statement update statement with where in array