mybatis 动态sql及参数传递

目录

使用场景

动态标签

if标签

where标签

choose、when、otherwise 标签

set标签

trim标签

forEach标签

参数传递

单个参数传递

多个参数传递

传入单个实体(JavaBean/Map)

传入多个实体

传入集合

批量新增


官网:动态 SQL_MyBatis中文网

使用场景

在实际开发过程中,我们往往需要编写复杂的SQL语句,拼接稍有不注意就会导致错误,Mybatis给开发者提供了动态SQL,大大降低了拼接SQL导致的错误。

动态标签

if标签

if标签通常用那个胡where语句,update语句,insert语句中,通过判断参数值来决定是否使用某个查询条件,判断是否更新某一个字段或插入某个字段

<if test="orderNum != null">
    #{orderNum,jdbcType=VARCHAR},
</if>

where标签

where标签通常与if标签配合使用,当if标签数量很多时可能会导致组合错误

  <select id="selectByParam" resultMap="BaseResultMap">
    select * from order_pri
    where
      <if test="id !=null">
        id = #{id, jdbcType =INTEGER}
      </if>
      <if test="orderNum !=null and orderNum !=''">
        and order_num = #{orderNum, jdbcType = VARCHAR}
      </if>
  </select>

当id=null 会 出现如下的sql拼写错误,

除了用where 1=1 and xxx 这样的方式外还可以使用<where>标签,<where>标签能够将开头(结尾的不行)多余的and/or去掉,同时<where>标签还能根据包含内容是否为空,决定where关键字的显示或隐藏。

正例:

反例:

choose、when、otherwise 标签

这三个标签需要组合在一起使用,类似于 Java 中的 switch、case、default。只有一个条件生效,也就是只执行满足的条件 when,没有满足的条件就执行 otherwise,表示默认条件。

set标签

采用update语句时,如果同时使用了<if>标签,如果某一行没有执行则会导致多余逗号,如果采用<set>标签则能够去掉结尾多余的逗号

反例:

加<set>标签后

注意:这里的set标签只能去掉语句最后一个逗号,其他的标点去不掉 多余的逗号也去不掉

trim标签

trim标签比较强大,可完成<set>或者<where>标记的功能,主要包含四个参数

  • prefix:在trim标签内sql语句加上前缀
  • suffix:在trim标签内sql语句加上后缀
  • prefixOverrides:指定去除多余的前缀内容,如:prefixOverrides=“AND | OR”,去除trim标签内sql语句多余的前缀"and"或者"or"。
  • suffixOverrides:指定去除多余的后缀内容。

<trim>替代<set>

  <!--使用trim代替<set>标签-->
  <update id="updateFieldV2" >
  update order_pri
    <!--开头用set 结尾去掉“,”逗号-->
    <trim prefix="set" suffixOverrides=",">
        <if test="orderNum !=null">
          order_num = #{orderNum, jdbcType = VARCHAR},
        </if>
        <if test="isDel !=null">
          is_del = #{isDel, jdbcType = INTEGER},
        </if>
    </trim>
  where
  id = #{id, jdbcType = VARCHAR }
  </update>

<trim>替代<where>

  <!--trim 代替<where>-->
  <select id="selectByFieldV2" resultMap="BaseResultMap">
    select * from
    order_pri
    <!--前缀加where 前缀如果有and去掉and,trim识别内容为空时自动解析为空-->
    <trim prefix="where" prefixOverrides="and">
      <if test="id !=null">
        and id = #{id, jdbcType =INTEGER}
      </if>
      <if test="orderNum !=null and orderNum !=''">
        and order_num = #{orderNum, jdbcType = VARCHAR}
      </if>
    </trim>
  </select>

当<trim>识别标签为空时,自动将内容处理为空,不添加where关键字。

forEach标签

foreach标签主要有以下参数:

  • collection配置的是传递进来的参数名称
  • item配置的是循环中当前的元素。
  • index配置的是当前元素在集合的位置下标。
  • open和 close配置的是以什么符号将这些集合元素包装起来。
  • separator是各个元素的间隔符。
<select id="selectBatchList" resultMap="BaseResultMap">
    select * from
    order_pri
    where id in
    <foreach collection="list" item="index" separator="," open="(" close=")">
      #{index}
    </foreach>
</select>

参数传递

单个参数传递

单参数可以直接进行传递Dao无需添加@Param注解

  <!-- Mapper -->
  List<OrderPri> selectById(String orderNum);

  <!-- xml -->
  <select id="selectById" resultMap="BaseResultMap">
    select * from order_pri
    where order_num = #{orderNum, jdbcType = VARCHAR}
  </select>

多个参数传递

多参数传递时xml无法识别key,需要用@Param标识一下进行传递

反例:

正例:

    <!--入参需要@Param-->
    List<OrderPri> selectByFieldV2(@Param("id") Integer id, @Param("orderNum") 
                                   String orderNum);
    <!--xml-->
    <select id="selectByField" resultMap="BaseResultMap">
    select * from
    order_pri
     <where>
      <if test="id !=null">
        and id = #{id, jdbcType =INTEGER}
      </if>
      <if test="orderNum !=null and orderNum !=''">
        and order_num like concat('%', #{orderNum, jdbcType = VARCHAR}, '%')
      </if>
     </where>
   </select>

传入单个实体(JavaBean/Map)

当参数<5 时建议多值传递,当参数>5时建议采用实体的方式

采用实体方式(不加@Param标识):

<!--Mapper-->
List<OrderPri> selectListParam(OrderPri orderPri);
    
<!--xml-->    
<select id="selectListParam" parameterType="com.wuxin.entity.OrderPri" 
                             resultMap="BaseResultMap">
    select
        <include refid="Base_Column_List"/>
    from  order_pri
    <where>
      <if test="id !=null">
        and id = #{id, jdbcType = INTEGER }
      </if>
      <if test="orderNum !=null ">
        and order_num  = #{orderNum, jdbcType = VARCHAR}
      </if>
      <if test="isDel !=null">
        and is_del = #{isDel, jdbcType = INTEGER}
      </if>
     </where>
</select>
    

如果加@Param注解则,xml中需要跟进@Param配置的名称进行实体中属性的读取

List<OrderPri> selectListParam(@Param("orderPri") OrderPri orderPri);


<select id="selectListParam" parameterType="com.wuxin.entity.OrderPri" resultMap="BaseResultMap">
    select
    <include refid="Base_Column_List"/>
    from  order_pri
    <where>
      <if test="orderPri.id !=null">
        and id = #{orderPri.id, jdbcType = INTEGER }
      </if>
      <if test="orderPri.orderNum !=null ">
        and order_num  = #{orderPri.orderNum, jdbcType = VARCHAR}
      </if>
      <if test="orderPri.startTime !=null">
        and start_time &lt;= #{orderPri.startTime, jdbcType = TIMESTAMP}
      </if>
      <if test="orderPri.endTime !=null">
        and end_time &gt;= #{orderPri.endTime, jdbcType = TIMESTAMP}
      </if>
    </where>
  </select>

当参数为map时同JavaBean,这里不再赘述。

传入多个实体

多实体传参时也要加@Param,否则会读不出来实体的属性

List<OrderPri> selectListByMulEntity(@Param("pri") OrderPri pri, @Param("dtl") 
                                      OrderDtl dtl);


<select id="selectListByMulEntity" resultMap="BaseResultMap">
    select
    p.id
    from  order_pri p left join
    order_dtl d on p.order_num = d.order_num
    <where>
      <if test="pri.id !=null">
        and p.id = #{pri.id, jdbcType = INTEGER }
      </if>
      <if test="pri.orderNum !=null ">
        and p.order_num  = #{pri.orderNum, jdbcType = VARCHAR}
      </if>
      <if test="pri.isDel !=null">
        and p.is_del = #{pri.isDel, jdbcType = INTEGER}
      </if>
      <if test="dtl.proId !=null">
        and d.pro_id = #{dtl.proId, jdbcType = INTEGER}
      </if>
    </where>
</select>

传入集合

1.当参数为Collection接口,转换为Map,Map的key为collection
2.当参数类型为List接口,“list”作为key,或用@Param(“xx”)修饰,遍历时需要collection="xx"
3.当参数为数组,也会转换为Map,Map的key为array

  • 传入数组时collection用array接:
  --Mapper
  List<OrderPri> selectBatch(int[] arr);  

  <!--数组-->
  <select id="selectBatch" resultMap="BaseResultMap">
    select * from
    order_pri
    where id in
    <foreach collection="array" index="item" open="(" close=")" separator=",">
       #{item}
    </foreach>
  </select>
  • 传入集合时用list接口(注意判空的写法)
  --Mapper
  List<OrderPri> selectBatchList(List<Integer> idList);
  
  --xml
  <!--动态集合-->
  <select id="selectBatchList" resultMap="BaseResultMap">
    select * from
    order_pri
    where status = 1
    <if test ="list!=null and list.size()>0" >
      and id in
          <foreach collection="list" item="item" separator="," open="(" close=")">
            #{item}
         </foreach>
    </if>
  </select>
  • 传入多个集合时
--Mapper
List<OrderPri> selectBatchListV2(@Param("idList") List<Integer> idList, 
                                     @Param("orders")List<String> orders);



<!--多个动态集合-->
  <select id="selectBatchListV2" resultMap="BaseResultMap">
    select * from
    order_pri
    where id in
    <foreach collection="idList" item="index" separator="," open="(" close=")">
      #{index}
    </foreach>
    and
    order_num in
    <foreach collection="orders" item="it" separator="," open="(" close=")">
      #{it}
    </foreach>
  </select>

批量新增

--mapper
int insertBatch(List<Model> list);


<insert id="insertBatch" parameterType="java.util.List">
    insert into table (field01, field02)
    values
    <foreach collection="list" item="item" separator =",">
      (#{item.field01,jdbcType=DATE}, #{item.field01,jdbcType=VARCHAR})
    </foreach>
</insert>

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值