为了防止SQL注入攻击,我项目中的所有SQL语句代码都应转换为参数化查询。但是当查询条件包含“ IN”情况时,我遇到了一个问题。这样(使用DB2数据库):
String employeeId = 'D2309'; String name = "%brady%"; List<Integer> userRights = new ArrayList<Integer>(); userRights.add(1); userRights.add(2); userRights.add(3); String sql = "SELECT * FROM T_EMPLOYEE WHERE EMPLOYEE_ID = ? AND NAME LIKE ? AND RIGHT IN (?)"; jdbcTemplate.query(sql, new Object[] {employeeId, name, userRights}, new EmployeeRowMapper());
上面的代码运行失败,但有以下例外:
org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; bad SQL grammar [SELECT * FROM T_EMPLOYEE WHERE EMPLOYEE_ID = ? AND NAME LIKE ? AND RIGHT IN (?)]; nested exception is com.ibm.db2.jcc.am.io: [jcc][1091][10824] [3.57.82] .... ERRORCODE=-4461, SQLSTATE=42815
这里的问题是JdbcTemplate不支持IN情况下的参数化查询吗?我知道可以通过NamedParameterJdbcTemplate来完成这项工作,是否只有NamedParameterJdbcTemplate可以进行案例查询?
非常感谢。
正如我在评论中已经提到的那样,我对这种解决方案不满意,因为它动态生成大量SQL语句。给定数量userRights在1到n之间,则高速缓存中最多需要n个准备好的语句。
userRights
下面应该工作(我没有尝试过)。
String employeeId = 'D2309'; String name = "%brady%"; List<Integer> userRights = new ArrayList<Integer>(); userRights.add(1); userRights.add(2); userRights.add(3); // build the input string StringBuilder sb = new StringBuilder(); for (int i = 0; i < userRights.size; i++) { sb.append("?"); if (i < userRights.size() - 1) { sb.append(", "); } } // build the SQL String sql = "SELECT * FROM T_EMPLOYEE WHERE EMPLOYEE_ID = ?" + " AND NAME LIKE ?" + " AND RIGHT IN (" + sb.toString() + ")"; // init the object array // size is employeeId + name + right Object[] param = new Object[2 + userRights.size()]; // fill it param[0] = employeeId; param[1] = name; for (int i = 0; i < userRights.size(); i++) { param[i + 2] = userRights.get(i); } jdbcTemplate.query(sql, param, new EmployeeRowMapper());