MyBatis-动态语句

Mybatis-动态语句

动态 SQL 是 MyBatis 的强大特性之一

通过在mapper.xml的标签来拼接所需的sql语句,例如不同的where条件


if标签

使用if标签可实现动态的sql语句

如果test属性中表达式的值为true,则将标签内的sql语句进行拼接,反之则忽略

test属性中的表达式的书写规则:

  • 逻辑与用and,逻辑或用or
  • 比较符号不推荐直接使用 < >因为老版本的MyBatis会错误的识别成标签结束符号,推荐使用实体符号
    • 实体符号是html中曾经使用过的转义符号:大于号用&gt 小于号用&lt

where标签

  • 如果where标签的子标签if标签满足条件,则会自动添加where关键字,反之缺省where关键字
  • 自动去掉多余的and和or关键字
<select id="queryByNameAndSalary" resultType="employee">
    select *
    from t_emp
    <where>
        <if test="name != null">
            emp_name = #{name}
        </if>
        <if test="salary != null">
            and emp_salary = #{salary}
        </if>
    </where>
</select>

set标签

和where标签功能大致相同,用于取代原本sql的update关键字

<update id="update">
    update t_emp
    <set>
        <if test="empName!=null">
            emp_name = #{empName} ,
        </if>
        <if test="empSalary!=null">
            emp_salary = #{empSalary}
        </if>
    </set>
    where emp_id = #{empId}
</update>

trim标签

trim中文释义:修剪

trim标签相当于自定义模式,用以替代where和set标签

  • prefix属性:如果if成立并且其标签下的语句存在,则自动补全prefix的值
  • prefixOverrides属性:自动修剪sql前多余的语句
  • suffixOverrides属性:自动修剪sql后多余的语句

可以理解成where和set只是定义好的trim

<select id="queryByNameAndSalaryTrim" resultType="employee">
    select *
    from t_emp
    <trim prefix="where" prefixOverrides="and">
        <if test="name != null">
            emp_name = #{name}
        </if>
        <if test="salary != null">
            and emp_salary = #{salary}
        </if>
    </trim>
</select>

choose、when和otherwise标签

这三个标签就相当于Java中的switch

<select id="queryByNameAndSalaryChoose" resultType="employee">
    select *
    from t_emp
    where
    <choose>
        <!--根据名字查询-->
        <when test="name != null">
            emp_name = #{name}
        </when>
        <!--根据工资查询-->
        <when test="salary != null">
            emp_salary = #{salary}
        </when>
        <!--如果以上两个条件都不满足,则查询全部-->
        <otherwise>1=1</otherwise>
    </choose>
</select>

choose中一定会执行一个where的判断条件,所以无需使用where标签来考虑是否忽略where

choose中只会执行一个where的判断条件,所以无需考虑and或or的语句修建问题

无论是查询结果为一个对象还是一个集合,resultType都会选择实体类,如果是集合的话resultType也是填写其泛型


foreach标签

  • collection属性:被遍历的数据
    • 使用param注解添加的别名
    • 使用arg0
    • 使用list
  • open属性:遍历之前要追加的字符串
  • close属性:遍历结束要追加的字符串
  • separator属性:每次遍历的分隔符号(最后一个不加符号)
  • item属性:遍历项

batch中文释义:批处理


mapper接口
// 批量处理crud
List<Employee> queryBatch(@Param("ids") List<Integer> ids);
int deleteBatch(@Param("ids") List<Integer> ids);
int insertBatch(@Param("employees") List<Employee> employees);
int updateBatch(@Param("employees") List<Employee> employees);
批量查询
<!--这个select不考虑传入的id集合为空的情况-->
<select id="queryBatch" resultType="employee">
    select * from t_emp
    where emp_id in
    <!--这个foreach的遍历结果为:(1,2,3,……)-->
    <foreach collection="ids" open="(" close=")" separator="," item="id">
        #{id}
    </foreach>
</select>
批量删除
<delete id="deleteBatch">
    delete from t_emp
    where emp_id in
    <foreach collection="ids" open="(" close=")" separator="," item="id">
        #{id}
    </foreach>
</delete>
批量插入

每一个item项中都是固定格式(empName,empSalary)所以没有遍历前后的追加括号

<insert id="insertBatch">
    insert into t_emp(emp_name,emp_salary)
    values
    <foreach collection="list" separator="," item="employee">
        (#{employee.empName},#{employee.empSalary})
    </foreach>
</insert>
批量更新

update比较特殊,没有什么能单独foreach的数据,所以将整条语句循环执行

<update id="updateBatch">
    <foreach collection="employees" item="emp">
        update t_emp
        set emp_name = #{emp.empName},emp_salary = #{emp.empSalary}
        where emp_id = #{emp.empId}
    </foreach>
</update>

但这种操作需要开启数据库支持,在mybatis-config.xml配置文件中,url一项后增加?allowMultiQueries=true参数即可

<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis-example?allowMultiQueries=true"/>
<property name="username" value="root"/>
<property name="password" value="Zhuwenxue2002"/>

sql&include标签

通过使用sql将重复的sql代码提取出来,通过include重新引用

<sql id="selectSql">
    select *
    from t_emp
</sql>
<select id="queryALl" resultType="employee">
    <include refid="selectSql"/>
</select>