动态sql,就是MyBatis中有一些标签,可以帮助我们来拼接sql。
一、 if
if标签可通过test属性的表达式进行判断,若表达式的结果为true,则标签中的内容会执行;反之标签中的内容不会执行。
应用场景:表单展示中通过过滤条件展示数据。
比如可以根据年龄或者性别查询员工数据。
输入参数两种取值可能,空字符串和null。
**Example:**根据年龄,部门,或者性别过滤查询。
mapper中查询函数定义:
List<Employee> getEmpByFilter(@Param("filter")Filter filter);
过滤条件Filter定义为:
package com.lucky.mybatis.bean;
public class Filter {
private String gender;
private int age;
private int departmentId;
public Filter() {
}
public Filter(String gender, int age, int departmentId) {
this.gender = gender;
this.age = age;
this.departmentId = departmentId;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getDepartmentId() {
return departmentId;
}
public void setDepartmentId(int departmentId) {
this.departmentId = departmentId;
}
@Override
public String toString() {
return "Filter{" +
"gender='" + gender + '\'' +
", age=" + age +
", departmentId=" + departmentId +
'}';
}
}
xml文件sql定义为
<select id="getEmpByFilter" resultMap="emp">
select * from t_emp where
<if test="filter.gender != null and filter.gender != '' ">
gender = #{filter.gender}
</if>
<if test="filter.age != null and filter.age != '' ">
and age = #{filter.age}
</if>
<if test="filter.departmentId != null and filter.departmentId != '' ">
and demp_id = #{filter.departmentId}
</if>
</select>
测试类
@Test
public void testIf() {
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);
Filter filter = new Filter("n", 22, 1);
List<Employee> employees = empMapper.getEmpByFilter(filter);
employees.forEach(System.out::println);
}
上面这个测试类中,filter三个属性是全部传入的,那如果只传入两个呢?
@Test
public void testIf2() {
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);
// 只用年龄和部门过滤
Filter filter = new Filter( 22, 1);
List<Employee> employees = empMapper.getEmpByFilter(filter);
employees.forEach(System.out::println);
}
这里就会出错,看一下Mybatis生成的sql语句为:
where 后面多了一个and关键字。这时候就需要where标签来动态生成where条件了。
二、where
只使用if标签,第一个条件不传入,where后面直接跟了and,会报错。或者条件都不传入,这样生成sql中多了where标签。
方法1: 使用where标签,动态生成where关键字,并且去除生成sql中前多余的and关键字,如果条件都不成立,不生成where标签。
where标签通常和if标签结合使用。
<select id="getEmpByFilter" resultMap="emp">
select * from t_emp
<where>
<if test="filter.gender != null and filter.gender != '' ">
gender = #{filter.gender}
</if>
<if test="filter.age != null and filter.age != '' ">
and age = #{filter.age}
</if>
<if test="filter.departmentId != null and filter.departmentId != '' ">
and demp_id = #{filter.departmentId}
</if>
</where>
生成sql语句为:
方法1: where 1=1
<select id="getEmpByFilter" resultMap="emp">
select * from t_emp where 1=1
<if test="filter.gender != null and filter.gender != '' ">
gender = #{filter.gender}
</if>
<if test="filter.age != null and filter.age != '' ">
and age = #{filter.age}
</if>
<if test="filter.departmentId != null and filter.departmentId != '' ">
and demp_id = #{filter.departmentId}
</if>
</select>
生成sql语句为:
三、trim
如下所示,and 关键字放到if标签内容的后面。测试时过滤条件不传入最后一个书香。
<select id="getEmpByFilter" resultMap="emp">
select * from t_emp
<where>
<if test="filter.gender != null and filter.gender != '' ">
gender = #{filter.gender} and
</if>
<if test="filter.age != null and filter.age != '' ">
age = #{filter.age} and
</if>
<if test="filter.departmentId != null and filter.departmentId != '' ">
demp_id = #{filter.departmentId}
</if>
</where>
</select>
这样的话,生成sql如下所示。如果最后一个条件为空这样生成sql里面就多了一个and。
,array的话key就是array。所以访问的时候,要用list(array).
<foreach collection="list" item="emp" separator=",">
item 循环变量
index 下标
separator forEach循环中分割符
open、close 设置当前循环由什么开始,由什么结束
批量添加
/**
* 批量插入员工信息
*
* @param employees employees
* @return int
*/
int insertEmps(@Param("emps") List<Employee> employees);
<insert id="insertEmps" useGeneratedKeys="true" keyProperty="id">
insert into t_emp values
<foreach collection="emps" item="emp" separator=",">
(null, #{emp.name},#{emp.age},#{emp.gender}, #{emp.departmentId})
</foreach>
</insert>
批量删除
方法1: delete in
delete 的时候 in里面的所有id要被()包围起来,这样就需要close和open属性了。
<delete id="deleteEmpByIds">
delete from t_emp where emp_id in
<foreach collection="ids" item="empId" separator="," open="(" close=")">
#{empId}
</foreach>
</delete>
方法2: where id = or id =
<delete id="deleteEmpByIds">
delete from t_emp where
<foreach collection="ids" item="empId" separator="or">
emp_id = #{empId}
</foreach>
</delete>
六、SQL片段
sql片段,可以记录一段公共sql片段,在使用的地方通过include标签进行引入。
<sql id="empColumns">
eid,ename,age,sex,did
</sql>
select <include refid="empColumns"></include> from t_emp