• MyBatis-动态SQL


    一、动态SQL主要使用以下标签:

    1、if判断

    2、choose(when otherwise):

      分支选择;带了break的swtich-case
      如果带了id就用id查,如果带了lastName就用lastName查;只会进入其中一个。

    3、trim 字符串截取(where(封装查询条件), set(封装修改条件))

    4、foreach 遍历集合

    二、案列

    1、<where if结合>

         <!-- 查询员工,要求,携带了哪个字段查询条件就带上这个字段的值 -->
         <!-- public List<Employee> getEmpsByConditionIf(Employee employee); -->
         <select id="getEmpsByConditionIf" resultType="com.atguigu.mybatis.bean.Employee">
             select * from tbl_employee
             <!-- where -->
             <where>
                 <!-- test:判断表达式(OGNL)
                 OGNL参照PPT或者官方文档。
                        c:if  test
                 从参数中取值进行判断
                 
                 遇见特殊符号应该去写转义字符:
                 &&:
                 -->
                 <if test="id!=null">
                     id=#{id}
                 </if>
                 <if test="lastName!=null &amp;&amp; lastName!=&quot;&quot;">
                     and last_name like #{lastName}
                 </if>
                 <if test="email!=null and email.trim()!=&quot;&quot;">
                     and email=#{email}
                 </if> 
                 <!-- ognl会进行字符串与数字的转换判断  "0"==0 -->
                 <if test="gender==0 or gender==1">
                      and gender=#{gender}
                 </if>
             </where>
         </select>

      说明:如果where 后面紧跟着and,<where>标签会自动去掉紧跟在后面的第一个and。

    2、

         <!--public List<Employee> getEmpsByConditionTrim(Employee employee);  -->
         <select id="getEmpsByConditionTrim" resultType="com.atguigu.mybatis.bean.Employee">
             select * from tbl_employee
             <!-- 后面多出的and或者or where标签不能解决 
             prefix="":前缀:trim标签体中是整个字符串拼串 后的结果。
                     prefix给拼串后的整个字符串加一个前缀 
             prefixOverrides="":
                     前缀覆盖: 去掉整个字符串前面多余的字符
             suffix="":后缀
                     suffix给拼串后的整个字符串加一个后缀 
             suffixOverrides=""
                     后缀覆盖:去掉整个字符串后面多余的字符
                     
             -->
             <!-- 自定义字符串的截取规则
          加上前缀 where 如果最后面有and,则去掉
        
    --> <trim prefix="where" suffixOverrides="and"> <if test="id!=null"> id=#{id} and </if> <if test="lastName!=null &amp;&amp; lastName!=&quot;&quot;"> last_name like #{lastName} and </if> <if test="email!=null and email.trim()!=&quot;&quot;"> email=#{email} and </if> <!-- ognl会进行字符串与数字的转换判断 "0"==0 --> <if test="gender==0 or gender==1"> gender=#{gender} </if> </trim> </select>

    3、

         <!-- public List<Employee> getEmpsByConditionChoose(Employee employee); -->
         <select id="getEmpsByConditionChoose" resultType="com.atguigu.mybatis.bean.Employee">
             select * from tbl_employee 
             <where>
                 <!-- 如果带了id就用id查,如果带了lastName就用lastName查;只会进入其中一个 -->
                 <choose>
                     <when test="id!=null">
                         id=#{id}
                     </when>
                     <when test="lastName!=null">
                         last_name like #{lastName}
                     </when>
                     <when test="email!=null">
                         email = #{email}
                     </when>
                     <otherwise>
                         gender = 0
                     </otherwise>
                 </choose>
             </where>
         </select>

    4、

         <!--public void updateEmp(Employee employee);  -->
         <update id="updateEmp">
             <!-- Set标签的使用 -->
             update tbl_employee 
            <set>
                <if test="lastName!=null">
                    last_name=#{lastName},
                </if>
                <if test="email!=null">
                    email=#{email},
                </if>
                <if test="gender!=null">
                    gender=#{gender}
                </if>
            </set>
            where id=#{id} 
    <!--         
            Trim:更新拼串
            update tbl_employee 
            <trim prefix="set" suffixOverrides=",">
                <if test="lastName!=null">
                    last_name=#{lastName},
                </if>
                <if test="email!=null">
                    email=#{email},
                </if>
                <if test="gender!=null">
                    gender=#{gender}
                </if>
            </trim>
            where id=#{id}  -->
         </update>

    5、

         <!--public List<Employee> getEmpsByConditionForeach(List<Integer> ids);  -->
         <select id="getEmpsByConditionForeach" resultType="com.atguigu.mybatis.bean.Employee">
             select * from tbl_employee
             <!--
                 collection:指定要遍历的集合:
                     list类型的参数会特殊处理封装在map中,map的key就叫list
                 item:将当前遍历出的元素赋值给指定的变量
                 separator:每个元素之间的分隔符
                 open:遍历出所有结果拼接一个开始的字符
                 close:遍历出所有结果拼接一个结束的字符
                 index:索引。遍历list的时候是index就是索引,item就是当前值
                               遍历map的时候index表示的就是map的key,item就是map的值
                 
                 #{变量名}就能取出变量的值也就是当前遍历出的元素
               -->
             <foreach collection="ids" item="item_id" separator=","
                 open="where id in(" close=")">
                 #{item_id}
             </foreach>
         </select>

    6、

          <!-- 
              抽取可重用的sql片段。方便后面引用 
              1、sql抽取:经常将要查询的列名,或者插入用的列名抽取出来方便引用
              2、include来引用已经抽取的sql:
              3、include还可以自定义一些property,sql标签内部就能使用自定义的属性
                      include-property:取值的正确方式${prop},
                      #{不能使用这种方式}
          -->
          <sql id="insertColumn">
                  <if test="_databaseId=='oracle'">
                      employee_id,last_name,email
                  </if>
                  <if test="_databaseId=='mysql'">
                      last_name,email,gender,d_id
                  </if>
          </sql>
         <!-- 批量保存 -->
         <!--public void addEmps(@Param("emps")List<Employee> emps);  -->
         <!--MySQL下批量保存:可以foreach遍历   mysql支持values(),(),()语法-->
        <insert id="addEmps">
             insert into tbl_employee(
                 <include refid="insertColumn"></include>
             ) 
            values
            <foreach collection="emps" item="emp" separator=",">
                (#{emp.lastName},#{emp.email},#{emp.gender},#{emp.dept.id})
            </foreach>
         </insert>

    7、

         <!-- 这种方式需要数据库连接属性allowMultiQueries=true;
             这种分号分隔多个sql可以用于其他的批量操作(删除,修改) -->
         <insert id="addEmps">
             <foreach collection="emps" item="emp" separator=";">
                 insert into tbl_employee(last_name,email,gender,d_id)
                 values(#{emp.lastName},#{emp.email},#{emp.gender},#{emp.dept.id})
             </foreach>
         </insert>

      说明:separator:分隔符。foreach中间的语句使用“;”分隔。

    8、Oracle数据库批量保存:

      Oracle不支持values(),(),()

      Oracle支持的批量方式
        1、多个insert放在begin - end里面
          begin
          insert into employees(employee_id,last_name,email)
          values(employees_seq.nextval,'test_001','test_001@atguigu.com');
          insert into employees(employee_id,last_name,email)
          values(employees_seq.nextval,'test_002','test_002@atguigu.com');
          end;
        2、利用中间表:
         insert into employees(employee_id,last_name,email)
         select employees_seq.nextval,lastName,email from(
         select 'test_a_01' lastName,'test_a_e01' email from dual
         union
         select 'test_a_02' lastName,'test_a_e02' email from dual
         union
           select 'test_a_03' lastName,'test_a_e03' email from dual
         )

         <insert id="addEmps" databaseId="oracle">
             <!-- oracle第一种批量方式 -->
             <!-- <foreach collection="emps" item="emp" open="begin" close="end;">
                 insert into employees(employee_id,last_name,email) 
                    values(employees_seq.nextval,#{emp.lastName},#{emp.email});
             </foreach> -->
             
             <!-- oracle第二种批量方式  -->
             insert into employees(
                 <!-- 引用外部定义的sql -->
                 <include refid="insertColumn">
                     <property name="testColomn" value="abc"/>
                 </include>
             )
                     <foreach collection="emps" item="emp" separator="union"
                         open="select employees_seq.nextval,lastName,email from("
                         close=")">
                         select #{emp.lastName} lastName,#{emp.email} email from dual
                     </foreach>
         </insert>

    9、Mybatis两个内置参数

      _parameter:代表整个参数

      单个参数:_parameter就是这个参数
        多个参数:参数会被封装为一个map;_parameter就是代表这个map

      _databaseId:如果配置了databaseIdProvider标签。
      _databaseId就是代表当前数据库的别名oracle

      

    <select id="getEmpsTestInnerParameter" resultType="com.atguigu.mybatis.bean.Employee">
                  <!-- bind:可以将OGNL表达式的值绑定到一个变量中,方便后来引用这个变量的值 -->
                  <bind name="_lastName" value="'%'+lastName+'%'"/>
                  <if test="_databaseId=='mysql'">
                      select * from tbl_employee
                      <if test="_parameter!=null">
                          where last_name like #{lastName}
                      </if>
                  </if>
                  <if test="_databaseId=='oracle'">
                      select * from employees
                      <if test="_parameter!=null">
                          where last_name like #{_parameter.lastName}
                      </if>
                  </if>
          </select>
      bind:可以将OGNL表达式的值绑定到一个变量中,方便后来引用这个变量的值

    10、抽取可重用的sql片段。方便后面引用

        1、sql抽取:经常将要查询的列名,或者插入用的列名抽取出来方便引用
        2、include来引用已经抽取的sql:
        3、include还可以自定义一些property,sql标签内部就能使用自定义的属性
          include-property:取值的正确方式${prop},
          #{不能使用这种方式}

      

    <sql id="insertColumn">
                  <if test="_databaseId=='oracle'">
                      employee_id,last_name,email
                  </if>
                  <if test="_databaseId=='mysql'">
                      last_name,email,gender,d_id
                  </if>
          </sql>

      

  • 相关阅读:
    自制 os 极简教程1:写一个操作系统有多难
    面试官问我redis数据类型,我回答了8种
    全网最硬核讲解计算机启动流程
    cinder-volume Required RPC API Old
    Docker swarm 容器流量追踪
    postgres schema访问权限设置
    骑士cms < 6.0.48任意文件包含漏洞简记
    Socket学习
    网络编程
    交换机和路由器的区别
  • 原文地址:https://www.cnblogs.com/zhaobingqing/p/7097863.html
Copyright © 2020-2023  润新知