Java对接SQL Server时Prepared Statement执行LIKE查询无返回结果如何解决
问题根因
你写的预编译SQL逻辑存在两处核心错误:
- 预编译语句的占位符
?仅支持传入值参数,不支持传入字段名、表名这类SQL标识符。你给第一个?传入字段名property的操作,实际执行时会被数据库当做字符串常量处理,等于执行的是where '字段名的字符串内容' like '匹配值',自然不会返回符合预期的结果。 - LIKE匹配的参数不需要手动加单引号,
setString方法会自动处理字符串的转义和边界包裹逻辑,你手动加单引号会导致单引号被识别为匹配值的一部分,和你实际要匹配的内容不符。
解决方案
字段名无法通过预编译占位符传入,因此需要做白名单校验后拼接,匹配值继续用预编译占位符传入,既保证安全性又能正常执行查询,修正后的代码如下:
List<Guest> guestList = new ArrayList<>(); // 第一步:做查询字段白名单校验,防止SQL注入,替换为你业务中实际允许查询的字段 List<String> allowedQueryProperties = Arrays.asList("guest_name", "contact_phone", "email"); if (!allowedQueryProperties.contains(property)) { throw new IllegalArgumentException("非法的查询字段参数"); } // 第二步:拼接经过校验的字段名,LIKE匹配值用预编译占位符 String query = "select * from Guests where " + property + " like ?"; PreparedStatement preparedStatement = connection.prepareStatement(query); // 第三步:给占位符赋值,仅加%通配符即可,无需手动加单引号 preparedStatement.setString(1, "%" + value + "%"); ResultSet resultSet = preparedStatement.executeQuery(); guestList = getGuestListFromResultSet(resultSet); return guestList;
补充说明
字段名的白名单校验是必须环节,只有经过校验的字段名拼接后才是安全的,配合值参数的预编译处理,整体方案可以完全规避SQL注入风险。
内容的提问来源于stack exchange,提问作者stefanp99
相关产品推荐
相关产品推荐

