简体   繁体   中英

JdbcTemplate does not support Parameterized Query 'IN' case? Must by NamedParameterJdbcTemplate?

Aimed at preventing SQL injection attacks, all the SQL Statement code in my project should transformed to Parameterized Query. But I got a problem when the query condition includes a 'IN' case. Like this (Using DB2 database):

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());

The above code runs failed with the exception:

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

The question here is that does not JdbcTemplate support Parameterized Query for IN case? and I know this work can be done by NamedParameterJdbcTemplate, and whether only NamedParameterJdbcTemplate can do IN case query?

Thanks a lot.

As I already mentioned in the comments, I'm not happy with this solution as it dynamically generates a number of SQL statements. Given the number of userRights is between 1 and n, it requires up to n prepared statements in the cache.

The below should work (I did not try it).

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());

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM