MyBatis学习:动态语句

学习之前

进行数据库查询时,有很多参数并不需要传入或没有值传入,具体情况随用户提交的请求确定。当查询条件不确定是,后端应该如何输入最终的SQL语句呢?这时候,MyBatis动态语句便出现了!

动态 SQL 是 MyBatis 的强大特性之一。使用动态 SQL 并非一件易事,但借助可用于任何 SQL 映射语句中的强大的动态 SQL 语言,MyBatis 显著地提升了这一特性的易用性。在 MyBatis 之前的版本中,需要花时间了解大量的元素。借助功能强大的基于 OGNL 的表达式,MyBatis 3 替换了之前的大部分元素,大大精简了元素种类,现在要学习的元素种类比原来的一半还要少。

一、if和where标签

动态SQL最常见的情景是根据输入条件,选择where语句或if语句。

public interface EmployeeMapper {
    // 根据员工的姓名和工资查询员工的信息
    // 如果传入属性,则判断相等;如果不传入参数,则不加where条件
    List<Employee> query(@Param("name") String name,@Param("salary") Double salary);
}
    <select id="query" resultType="com.landy.pojo.Employee">
        select emp_name , emp_salary from t_emp
        <where>
            <if test="name != null">
                emp_name = #{name}
            </if>
            <if test="salary != null and salary &gt; 100">
                and emp_salary = #{salary}
            </if>
        </where>
    </select>

<if> 标签:判断test=""内部条件是否成立,即该参数是否传入,或该参数是否满足某一条件。大于号用&gt;代替,小于&lt;号用代替 

<where> 标签:当条件只有部分满足且没有where标签时,可能出现错误。

  • 当第二个条件满足,第一个条件不满足,出现...where and...语法错误
  • 若条件都不满足,出现...where语法错误

故需要where标签动态添加where关键字:

  • 自动添加where关键字。where标签内部,有任何一个<if>标签满足则自动添加。

二、set标签

<set>标签主要用于更新操作

 // 根据员工id更新员工数据,只有传入的name和salary都不为空时才更新
    int update(@Param("id") Integer id, @Param("name") String name, @Param("salary") Double salary);
    <update id="update">
        update t_emp
            <set>
                <if test="name !=null">
                    emp_name = #{name}
                </if>
            <if test="salary != null">
                ,emp_salary = #{salary}
            </if>
            </set>
            where  emp_id = #{id}
    </update>

<set>标签作用与<where>标签相似,用于动态添加set关键字。

三、trim标签

动态添加指定前后缀,增加标签灵活度。

List<Employee> queryTrim(@Param("name") String name,@Param("salary") Double salary);
    <select id="queryTrim" resultType="com.landy.pojo.Employee">
        select emp_name , emp_salary from t_emp
        <trim prefix="where" prefixOverrides="and | or" suffixOverrides="and | or">
            <if test="name != null">
                emp_name = #{name}
            </if>
            <if test="salary != null and salary &gt; 100">
               and emp_salary = #{salary}
            </if>
        </trim>
    </select>

<trim>标签:控制条件部分的两端是否包含某些字符

  • prefix属性:指定需要动态添加的前缀。例子中意为动态添加where标签
  • suffix属性:指定要动态添加的后缀
  • prefixOverrides属性:需要动态删去或忽略的重复前缀内容,用 | 来分隔多个内容。例子中意为忽略SQL语句前多余的and和or
  • suffixOverrides属性:需要需要动态删去或忽略的重复后缀内容,用 | 来分隔多个内容。例子中意为忽略SQL语句后多余的and和or

四、choose / when / otherwise标签

类似java中的switch-case语句,在多条分支中,仅执行一个语句。

  • 从上到下依次判断<when>是否可执行
  • 遇到第一个满足条件的<when>分支标签会被采纳
  • 当一个标签被采纳后,其他分支将不再考虑
  • 当所有分值都不满足,则执行<otherwise>条件分支
 // 如果name非空则使用name进行查询,若果name为空,salary非空则使用salary进行查询,否则全部返回
    List<Employee> queryCase(@Param("name") String name,@Param("salary") Double salary);
    <select id="queryCase" resultType="com.landy.pojo.Employee">
        select emp_name , emp_salary 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>

五、foreach标签

对传入的集合对象执行批量操作。

    // 根据多个id批量查询
    List<Employee> queryBatch(@Param("ids") List<Integer> ids);
    // 根据多个id批量删除
    int deleteBatch(@Param("ids")List<Integer> ids);
    int insertBatch(@Param("emps")List<Employee> employees);
    int updateBatch(@Param("emps")List<Employee> employees);
<!--
    collection:待遍历的集合
    open:遍历之前要追加的字符串
    close:遍历结束后要追加的字符串
    separator:遍历集合中元素之间的分隔符
    item:每个遍历项的名称
-->
    <select id="queryBatch" resultType="emp">
        select * from t_emp
            where emp_id in
            <foreach collection="ids" open="(" separator="," close=")" item="id">
                #{id}
            </foreach>
    </select>
<!--
    上述标签等于语句:select * from t_emp where emp_id in (1,2,3,4,5)
-->
    <delete id="deleteBatch">
        delete from t_emp
            where emp_id in
            <foreach collection="ids" open="(" separator="," close=")" item="id">
                #{id}
            </foreach>
    </delete>
<!--
    如果一个语句需要重复多词执行,需要声明多语句
    数据连接池配置时携带参数 ...//database?allowMultiQueries=true
  -->
    <update id="updateBatch">
            <foreach collection="emps"  separator=";" item="emp">
                update t_emp
                    set emp_name = #{emp.empName},emp_salary = #{emp.empSalary}
                    where emp_id = #{emp.empId}
            </foreach>
    </update>

    <insert id="insertBatch">
        insert into t_emp (emp_name,emp_salary) values
            <foreach collection="emps" separator="," item="emp">
                (#{emp.empName},#{emp.empSalary})
            </foreach>
    </insert>

<foreach>标签:包裹需要重复执行的语句模块,可以是整句,也可以是部分。

        collection属性:传入的集合参数,需要循环操作的list

        open属性:遍历之前追加的字符串,如“(”

        seperator属性:遍历集合元素之间的分隔符,如“,”

        close属性:遍历之后需要追加的字符串,如“)”

如果完整语句被<foreach>标签包裹,且需要多词被执行,seperator为分号“;”,同时需要在config文件中添加相关配置:

设置参数://database?allowMultiQueries=true

<property name="url" value="jdbc:mysql://localhost:3306/mybatis-example?allowMultiQueries=true"/>

六、SQL片段复用

可以将反复出现、常用的SQL语句抽离出来,需要的时候使用标签引用即可,简化开发。

    <sql id="selectSql">
        select * from t_emp
    </sql>
    <select id="queryBatch" resultType="emp">
            <include refid="selectSql"></include>
            where emp_id in
            <foreach collection="ids" open="(" separator="," close=")" item="id">
                #{id}
            </foreach>
    </select>

将需要抽取的SQL语句用<sql>标签包裹,并注明唯一标识id。后续重复使用时使用<include id="myId">引用即可

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值