1.1.需求
- 做员工高级查询,根据用户输入的条件来查询,通常需要动态的拼接SQL:
- 页面功能
<table border="1" align="center" cellspacing="0" width="400px">
<form action="跳转后台controller地址" method="post">
员工姓名:<input type="text" name="name">
员工年龄:<select name="ageIndex">
<option value="1">18以下(不包含18)</option>
<option value="2">18-30(不包含30)</option>
<option value="3">30-50(不包含50)</option>
<option value="4">50以上(包含50)</option>
</select>
<input type="submit" value="查询">
</form>
</table>
3. 目前传参可以直接使用名称来传递,但是如果后期条件增多,这种方式就不是太好,所以会封装一个查询条件的对象,还需要去准备一个带有条件的查询方法。例如:empQuery,findAll(empQuery,query)
1.2.实现
1.准备一个条件查询的类
package cn.itsource.zy.query;
/**
* 创建一个query包
* 设置需要查询的条件
* 员工查询对象
* 封装需要的查询条件
*/
public class EmpQuery {
//用于接收前端页面传递的参数
private String name;
private Integer ageIndex;
提供get和set方法
}
2.定义映射器接口,在接口中定义方法,并在service中定义,controller层调用
mapper:
service:
controller:
页面:
3.编写Mapper映射文件
<!--
带有自定义条件的查询语句
empQuery 同样需要设置别名
在app...Con...xml中设置cn.itsource.zy.query
-->
<select id="findAll" parameterType="empQuery" resultType="Emp">
select * from emp
<!--在下面添加查询的条件-->
</select>
完善查询条件
注意:
<if>标签:
(1) 作用:
① 用于判断条件是否满足,满足就拼接sql,不满足不拼接
② 会自动加上空格,避免造成sql语法错误
<!--
在下面添加查询的条件
需要判断有没有传递name这个参数,如果没有传递,则应该判断是否加条件
这是根据具体的条件查询
-->
<if test="name!=null and name!=''">
where name=#{name}
</if>
(2) 注意:
① 如果参数是字符串类型,那么需要判断null和空字符串【去空白】;
② 如果参数是数值类型,只需要判断null值;
<if test='name != null and !"".equals(name.trim())'>
where name=#{name}
</if>
4.模糊查询:
方案1:直接用#,日志中发现值并没有替换,所有不能直接使用#
and (name like '%#{keywords}%' or password like '%#{keywords}%')
方案2:使用$符号,测试成功,但是可能会出现SQL注入
and (name like '%${keywords}%' or password like '%${keywords}%')
方案3:用mysql中字符串拼接函数concat,测试成功,也不会出现SQL注入,建议使用
<!--模糊匹配查询-->
<if test="name!=null and name!=''">
where name like concat('%',#{name},'%')
</if>
5.如果有特殊符号:
(1) 在xml的转义字符:
① 符号:<【<】、<=【<=】、>【>】、>=【>=】、&【&】、'【'】 、 "【"】
② 【gt -> greater than(大于 )lt -> less than(小于)】
(2) 或者可以用CDATA代码段:
① 大于等于 <![CDATA[ >= ]]>
② 小于等于 <![CDATA[ <= ]]>
<!--当选项有多个是,需要判断,采用choose when-->
<if test="ageIndex!=null">
<choose>
<!--
使用特殊符号表示大小于符号
如: < <
> >
-->
<when test="ageIndex==1">
where age < 18
</when>
<when test="ageIndex==2">
<![CDATA[where age >= 18 and age < 30]]>
</when>
</choose>
</if>
6.<where>标签:
(1) 问题:以上拼接方式在多个条件时,会有多余的where条件,导致查询的语法错误,就使用where标签解决
(2) 作用:
① 拼接了一个where
② 忽略第一个多余的and 或者 or
③ 自动加空格
<where>
<!--模糊匹配查询-->
<if test="name!=null and name!=''">
<!--添加and表示多条件 但在使用where标签时,会自动省略,替换为where-->
and name like concat('%',#{name},'%')
</if>
<if test="ageIndex!=null">
<choose>
<when test="ageIndex==1">
and age < 18
</when>
<when test="ageIndex==2">
<![CDATA[and age >= 18 and age < 30]]>
</when>
</choose>
</if>
</where>
7.如果语句被多个地方调用可以使用<sql>抽取和<include>调用
(1) 使用<sql>抽取:
<sql id="address">
<if test='address != null and !"".equals(address.trim())'>
and address like CONCAT('%',trim(#{address}),'%')
</if>
</sql>
(2) 使用<include>调用:
<include refid="address"></include>