什么是动态模糊查询?直接例子说明了嗷

例子:

需求:

用户可能会填写名称并且按照名称模糊查询,可能会填写最高价格,可能会填写最低价格,查询是一次请求,我们需要在一次请求内,处理可能会到来的三个数据

为什么这算是问题?因为我们的需求是要写sql,如果你的三个参数中的某一个参数值为空,那你的sql就可能会 : select * from xxx where ab like ‘%%’ and b=

上面的sql你想知道会是什么异常吗?反正我不想知道

image-20200815204118279

思路:

参数相对较多,为了方便处理首先封装为实体类,之后可以分为很多种方式进行查询,我挨个说。

DataVo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.ls.domain;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class DataVo {
private String proName;
private String max;
private String min;

}

第一种

思路:

sql动态拼接可以借助mabatis的 example 类来帮助实现:

dao

1
2
3
@Mapper
public interface ProductDAO extends tk.mybatis.mapper.common.Mapper<Product> { //没错,继承通用mapper就行了,不需要任何多余代码
}

service:

这里是我们战斗的主阵地了啊

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public List<Product> duocha(DataVo voVoVoVo) {
Example example = new Example(Product.class);
Example.Criteria criteria = example.createCriteria();
if (!"null".equals(voVoVoVo.getProName()) && StringUtils.isNotBlank(voVoVoVo.getProName())) {
criteria.andLike("productName", "%"+voVoVoVo.getProName()+"%");
}

if (!"null".equals(voVoVoVo.getMax()) && StringUtils.isNotBlank(voVoVoVo.getMax())) {
criteria.andLessThanOrEqualTo("productPrice", voVoVoVo.getMax());
}
if (!"null".equals(voVoVoVo.getMin()) && StringUtils.isNotBlank(voVoVoVo.getMin())) {
criteria.andGreaterThanOrEqualTo("productPrice", voVoVoVo.getMin());
}
return productDAO.selectByExample(example);
}

就是根据传递进来的实体类,判断是否有值,有值则添加一个判断条件,以此达成动态拼接

第二种

思路:

动态拼接不是只能在service进行的,还可以在xml中,不知道你还记得吗?

dao:

1
2
3
4
5
6
7
8
@Mapper
public interface ProductDAO extends tk.mybatis.mapper.common.Mapper<Product> {

//相对于刚才的dao,多了一个抽象方法


public List<Product> mohu(DataVo dataVo);
}

xml:

这里是主战场

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ls.dao.ProductDAO">

<select id="mohu" resultType="com.ls.domain.Product" parameterType="com.ls.domain.DataVo">
select * from tb_product
<where>
<if test="proName !=null and proName !='null'">

<bind name="gou" value="'%'+proName+'%'"/>
and product_name like #{gou}
</if>
<if test="max !=null and max!='null'">
and product_price &lt;= #{max}
</if>
<if test="min !=null and min!='null'">
and product_price &gt;= #{min}
</if>
</where>
</select>
</mapper>

主要注意band标签,可以通过这个标签,自定义一个name作为属性,将实际要传进来的数值通过value可以拼接为想要的字符,最后引用变量只需要引用 name就行了

注意where,可以去掉所有多余的sql 关键字,if就是用来判断的

注意namespace,要是我们抽象类的路径位置

注意方法名要与 xml中的id相同才可以调用得到具体的xml中的动态拼接

添加resources

因为我们用的xml并没有 类似 @mapper的注解 所以无法扫描到,通常我们将这个xml放到resource里面,但是我为了方便看,放到了dao层,所以还要再pom中添加配置

在build下添加在build下添加在build下添加在build下添加在build下添加在build下添加

1
2
3
4
5
6
7
8
9
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>

service:

1
2
3
4
5
6
public void changshi(DataVo dataVo){
List<Product> mohu = userDAO.mohu(dataVo);
for (Product product : mohu) {
System.out.println(product);
}
}

这次service很简洁了

第三种:

基于第一种与第二种的结合

思路:

动态拼接,是可以直接在 @select 注解中完成的,不hi必须大费周章的在别的类,或者是方法中完成。

dao:

主战场

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Select("<script>select * from tb_product\n" +
" <where>\n" +
" <if test=\"proName !=null and proName !='null'\">\n" +
"\n" +
" <bind name=\"gou\" value=\"'%'+proName+'%'\"/>\n" +
" and product_name like #{gou}\n" +
" </if>\n" +
" <if test=\"max !=null and max!='null'\">\n" +
" and product_price &lt;= #{max}\n" +
" </if>\n" +
" <if test=\"min !=null and min!='null'\">\n" +
" and product_price &gt;= #{min}\n" +
" </if>\n" +
" </where></script>")
public List<Product> mohu(DataVo dataVo);

只需要在这里处理完,就不需要任何其他的操作了

至此,总结:想要实现动态拼接,还是需要比较繁琐的操作的,但是只要你的mybatis用的熟练,这就不是问题