动态SQL

761 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第10天,点击查看活动详情

动态SQL

if标签

if标签可通过test属性的表达式进行判断,若表达式的结果为true,则标签中的内容会执行;反之标签中的内容不会执行

接口

List<Emp> getEmpByCondition(Emp emp);

配置文件

<select id="getEmpByCondition" resultType="Emp">
    select * from t_emp where
    <if test="empName !=null and empName !=''">
        emp_name=#{empName}
    </if>
    <if test="age !=null and age !=''">
        and age=#{age}
    </if>
    <if test="gender !=null and gender !=''">
        and gender=#{gender}
    </if>
</select>

实现

public void getEmpByCondition(){
    SqlSession sqlSession = SqlSeesionUtils.getSqlSession();
    DynamicSqlMapper mapper = sqlSession.getMapper(DynamicSqlMapper.class);
    Emp emp = new Emp(1, "Sentiment", 20, "男");
    List<Emp> result = mapper.getEmpByCondition(emp);
    result.forEach(System.out::println);
}

where标签

在使用if标签时存在一个问题:若第一个条件不成立,第二个条件成立的话 ,则第一个标签不会执行,但由于第二个标签中存在and关键字若第一个标签不执行直接执行第二个标签的话,会将and直接拼接到where 后边,导致语句执行失败即:

此时就有了三个解决办法:

1=1恒成立

在where后边加上恒成立条件1=1,之后的每个if标签的语句前都加上and,此时无论标签执不执行,语句都成立

<select id="getEmpByCondition" resultType="Emp">
    select * from t_emp where 1=1
    <if test="empName !=null and empName !=''">
        and emp_name=#{empName}
    </if>
    <if test="age !=null and age !=''">
        and age=#{age}
    </if>
    <if test="gender !=null and gender !=''">
        and gender=#{gender}
    </if>
</select>

where标签

在if标签前加上where标签:

  • 若where标签中有条件成立,会自动生成where关键字
  • where标签会自动将内容中前边多余的and去掉
  • 若where标签中没有任何一个条件成立,则where没有任何功能
<select id="getEmpByCondition" resultType="Emp">
    select * from t_emp
    <where>
        <if test="empName !=null and empName !=''">
            emp_name=#{empName}
        </if>
        <if test="age !=null and age !=''">
            and age=#{age}
        </if>
        <if test="gender !=null and gender !=''">
            and gender=#{gender}
        </if>
 </where>
</select>

trim标签

除了前两种方法外,还可以使用trim标签

prefix/suffix:在内容前/后加上指定内容

prefixOverrides/suffixOverrides:在内容前/后去掉多余的指定内容

<select id="getEmpByCondition" resultType="Emp">
    select * from t_emp
    <trim prefix="where" prefixOverrides="and">
        <if test="empName !=null and empName !=''">
            emp_name=#{empName}
        </if>
        <if test="age !=null and age !=''">
            and age=#{age}
        </if>
        <if test="gender !=null and gender !=''">
            and gender=#{gender}
        </if>
    </trim>
</select>

choose、when、otherwise

when相当于ifelse、otherwse相当于else,所以when至少有一个而otherwise至多有一个,都放在choose标签中

when语句中不需要加and,因为when相当于ifelse语句,所以三个when标签至多只会执行一个

<select id="getEmpByChoose" resultType="Emp">
    select * from t_emp
    <where>
        <choose>
            <when test="empName !=null and empName !=''">
                emp_name=#{empName}
            </when>
            <when test="age !=null and age !=''">
                age=#{age}
            </when>
            <when test="gender !=null and gender !=''">
                gender=#{gender}
            </when>
        </choose>
    </where>
</select>

foreach标签

collection:设置循环中的数组或集合

item:表示数组或集合中的每一个数组

separator:每次循环之间数据的分隔符

index:指定一个名字,用于表示在循环过程中,每次循环到的位置

open:表示该循环语句以什么开始

close:表示以什么结束

批量添加(集合)

接口

void insertMoreEmp(@Param("emps") List<Emp> emps);

配置文件

由于emps是集合类型,所以需要用item=emp,设置每次执行的迭代名,separator=","以逗号分割每次循环

<insert id="insertMoreEmp">
    insert into t_emp values
    <foreach collection="emps" item="emp" separator=",">
        (#{emp.empId},#{emp.empName},#{emp.age},#{emp.gender},null)
    </foreach>
</insert>

实现

public void insertMoreEmp(){
    SqlSession sqlSession = SqlSeesionUtils.getSqlSession();
    DynamicSqlMapper mapper = sqlSession.getMapper(DynamicSqlMapper.class);
    Emp emp1 = new Emp(5, "aaa", 20, "男");
    Emp emp2 = new Emp(6, "bbb", 20, "男");
    Emp emp3 = new Emp(7, "ccc", 20, "男");
    List<Emp> emps = Arrays.asList(emp1, emp2, emp3);
    mapper.insertMoreEmp(emps);
}

批量删除(数组)

接口

void deleteMoreEmp(@Param("empids") int[] empids);

配置文件

open、close设置语句开头结尾,分隔符也可以用or

<delete id="deleteMoreEmp">
    delete from t_emp where emp_id in
    <foreach collection="empids" item="empid" separator="," open="(" close=")">
        #{empid}
    </foreach>
</delete>

实现

public void deleteMoreEmp(){
    SqlSession sqlSession = SqlSeesionUtils.getSqlSession();
    DynamicSqlMapper mapper = sqlSession.getMapper(DynamicSqlMapper.class);
    int[] ints = {5, 6, 7};
    mapper.deleteMoreEmp(ints);
}

sql标签

可以记录一段sql,在需要用的她方使用include标签进行引用

<sql id="sqls">
    emp_id,emp_name,age,gender
</sql>
<select id="getEmpByCondition" resultType="Emp">
    select <include refid="sqls"></include> from t_emp
</select>