问题:
在用户使用查询功能的时候,从前端发送给我们后端的信息(如下图4个信息),有可能不是4个都填上的,所以导致我们Dao层的sql语句不能够写死,那么我们该如何添加这个变化的变量进去sql语句呢?
解决代码:
首先,我们将从前端获取的数据在web层的servlet封装进map集合:
然后在Dao层写上如下代码:
public class SearchProductDao {
JdbcTemplate jdbcTemplate = new JdbcTemplate(JdbcUtils.getDataSource());
public List<Product> searchProduct(Map<String, Object> conditionMap) throws SQLException {
//因为不知道用户输入的是多小个数据,所以我们使用拼接字符串的方式编写sql语句
//使用where 1=1,是为了拼接以下条件成立的字符串(and xxxxx),因为以下字符串都包含and,所以需要一个where,如果不写where = 1,那么语句将变成"SELECT * FROM products AND XXXX "显然是错误的,用户一个也不写where = 1也不会对语句有任何影响
StringBuilder sqlBuilder = new StringBuilder("SELECT * FROM products WHERE 1=1 ");
//因为语句不确定长度,所以用先List来存储需要添加的语句
List<Object> paramList = new ArrayList<Object>();
//从map集合获取数据,判定是否有效字符串,采用模糊搜索
//如果成功"SELECT * FROM products WHERE 1=1 and pname like ? "
String pname = (String) conditionMap.get("pname");
//如果rname不为空或不为空字符串就有效,就过滤
if (pname != null && !pname.trim().equals("")) {
//and前面需要添加一个空格,为防止语句变成“1and”,而使语句报错
sqlBuilder.append(" and pname like ?");
//如果成立则添加进list集合
paramList.add("%" + pname + "%");
}
//如果成功"SELECT * FROM products WHERE 1=1 and Price >= ? "如此类推
String minPrice = (String) conditionMap.get("minPrice");
if (minPrice != null && !minPrice.trim().equals("")) {
sqlBuilder.append(" and Price >= ?");
paramList.add(minPrice);
}
String maxPrice = (String) conditionMap.get("maxPrice");
if (maxPrice != null && !maxPrice.trim().equals("")) {
sqlBuilder.append(" and Price <= ?");
paramList.add(maxPrice);
}
String category = (String) conditionMap.get("category");
if (category != null && !category.trim().equals("")) {
sqlBuilder.append(" and category like ?");
paramList.add(category);
}
//如果需要排序可在最后再拼接字符串 sql += "order by desc``````写具体条件"
//使sql语句变成1-3部分"SELECT * FROM products WHERE 1=1 " + "and xxxxx" + "order by xxxx"
//执行sql语句,根据上面条件判断可知占位符"?"的个数是0~4个,说明占位符格式是否动态变化的
/*
* jdbcTemplate使用sql中占位符"?"传入值的方式有2种:
* 方式1.jdbcTemplate.query(sql, new BeanPropertyRowMapper<Product>(Product.class),占位值1,占位值2,...);
* 方式2.jdbcTemplate.query(sql, new BeanPropertyRowMapper<Product>(Product.class),固定长度的数组);
* */
//将上面0~4个占位符收集到固定长度数组里面(动态长度占位符使用List集合收集,List集合可以转换为固定长度数组)
//paramsList里面存储着0-4个占位符值
//最后在这里使用paramList.toArray()变成数组
return jdbcTemplate.query(sqlBuilder.toString(), new BeanPropertyRowMapper<Product>(Product.class), paramList.toArray());
}
}