mybatis動態SQL與批量插入


一 前言

本篇文章需要有一定得mybatis入門基礎才能學習;如果是初學者請參考以下鏈接進行系統學習

  1. mybatis入門 https://blog.csdn.net/youku1327/article/details/103339617
  2. mybatis初級映射 https://blog.csdn.net/youku1327/article/details/103411829
  3. mybatis配置 https://blog.csdn.net/youku1327/article/details/103604724

當然如果是資深讀者,又沒有經過系統得學習,可以直接入主本篇,帶你一覽動態標簽使用方式;

動態SQL可以通過給定不同得條件,執行不同得SQL語句,實現動態SQL得方式就是通過mybatis提供得標簽語法進行配置;

二 動態SQL標簽

2.1 if 標簽

  1. if 標簽表示條件判斷
  2. customer_name 不為空時會執行當前if標簽的內容;此時的sql 語句 就是 select * from customer where and customer_name = #{customer_name}
  3. gender不為空時會執行if語句;此時執行的sql語句就是 select * from customer where 1 = 1 and gender = #{gender}
  4. customer_name 和 gender 標簽都不為空時;此時執行的sql語句就是 select * from customer where and customer_name = #{customer_name} and gender = #{gender}
    <select id="getCustomer" resultType="com.zszxz.dynamic.entity.Customer" >
        select
            *
        from `customer`
        where 1=1 
            <if test="customer_name!=null and customer_name!='' ">
                and `customer_name` = #{customer_name}
            </if>
            <if test="gender!=null and gender!=''">
                and `gender` = #{gender}
            </if>
    </select>

2.2 where 標簽

2.1 中我們在 where 后面使用 1=1 的操作,表示永遠為真,不是一個規范的數據庫操作;我們通常在select 語句的條件部分會使用 where 標簽 與 if 標簽 搭配使用,此時就可以消除 1=1操作帶來的負面影響

    <select id="getCustomer" resultType="com.zszxz.dynamic.entity.Customer" >
        select
            *
        from `customer`
        <where>
            <if test="customer_name!=null and customer_name!='' ">
                and `customer_name` = #{customer_name}
            </if>
            <if test="gender!=null and gender!=''">
                and `gender` = #{gender}
            </if>
        </where>
            
    </select>

2.3 choose, when, otherwise標簽

有時候需要一種場景就是 if else 形式的判斷,如下示例中

  1. 當 customer_name 不為空 會執行 when標簽體的內容;此時sql 就是 select gender from customer;
  2. 當輸入的條件customer_name 為空時會執行otherwise標簽體的內容;此時sql就是 select * from customer;
  <select id="getCustomer" resultType="com.zszxz.dynamic.entity.Customer" >
        select
        <choose>
            <when test="customer_name=!null">
                `gender`
            </when>
            <otherwise>
                *
            </otherwise>
        </choose>
        from `customer`
    </select>

2.4 trim標簽

先說下trim 屬性 代表的涵義

  1. prefix 表示前綴,就是會為 trim 標簽體加一個前綴;
  2. prefixOverrides 表示會將匹配到的第一個字符串去除;
  3. suffix 表示后綴,會為 trim 標簽體加一個后綴內容;
  4. suffixOverrides表示會將匹配到的最后一個字符串去除;

如下示例中 執行的SQL語句就是 select * from customer where customer_name = #{customer_name}

    <select id="getCustomer" resultType="com.zszxz.dynamic.entity.Customer" >
        select
            *
        from `customer`
        <trim prefix="where" prefixOverrides="and">
            and `customer_name` = #{customer_name}
        </trim> 

    </select>

2.5 set標簽

set 標簽 只有在 更新操作中能用到;如下示例中set標簽會默認將最后一個多余的逗號去除;

    <update id="updateCustomer" parameterType="com.zszxz.dynamic.entity.Customer">
        update `customer`
        <set>
            <if test="customer_name!=null">
                `customer_name` = #{customer_name},
            </if>
            <if test="gender!=null">
                `gender` = #{gender},
            </if>
            <if test="telephone!=null">
                `telephone` = #{telephone},
            </if>
            <if test="register_time!=null">
                `register_time` = #{register_time},
            </if>
        </set>
        <where>
            id = #{id}
        </where>
    </update>

如果所有的參數都不為空 執行的語句如下

update `customer` SET `customer_name` = ?, `gender` = ?, `telephone` = ?, `register_time` = ? WHERE id = ? 

set標簽此時會等效於trim標簽的如下形式

<trim prefix="SET" suffixOverrides=",">
  ...
</trim>

2.6 foreach 標簽實現in

foreach 標簽屬性說明如下

  1. collection 參數
  2. open 前綴
  3. separator 分割符
  4. item 迭代中取得值,當入參數是Map.Entry或者map就是其 中 得值
  5. index 迭代中得鍵,當入參數是Map.Entry或者map就是其 中 得鍵;若入參是組數就是索引;
    <select id="getCustomerById" resultType="com.zszxz.dynamic.entity.Customer" >
        select
            *
        from `customer`
        <where>
            <if test="ids!=null">
                and id in 
                <foreach collection="ids" open="(" separator="," item="id" index="i"  close=")">
                    #{id}
                </foreach>
            </if>
        </where>
    </select>

最終得SQL語句執行形式如下

select * from `customer` WHERE id in ( ? , ? )

2.7 foreach標簽實現批量插入

在xml中添加如下語句

 <insert id="addCustomer" >
         insert into `customer`(
            `customer_name`,
            `gender`,
            `telephone`,
            `register_time`
         )values 
         <foreach collection="customers"  separator="," item="customer" index="i">
             (
                 #{customer.customer_name},
                 #{customer.gender},
                 #{customer.telephone},
                 #{customer.register_time}
             )
         </foreach>
    </insert>

部分測試類如下 在 for循環中創建3 個客戶對象放入List,然后執行批量插入方法

    @Test
    public void testInsert(){
        // 獲得mapper的形式
        CustomerMapper mapper = sqlSession.getMapper(CustomerMapper.class);
        ArrayList<Customer> list = new ArrayList<>();
        for (int i = 0; i < 3; i++) {
            Customer customer = new Customer();
            customer.setCustomer_name("知識追尋者");
            customer.setGender("男");
            customer.setTelephone("999"+i);
            list.add(customer);
        }
        // 添加客戶
        mapper.addCustomer(list);
        sqlSession.commit();
        sqlSession.close();
    }

最終執行得SQL語句格式如下

insert into `customer`( `customer_name`, `gender`, `telephone`, `register_time` )values ( ?, ?, ?, ? ) , ( ?, ?, ?, ? ) , ( ?, ?, ?, ? ) 

2.8 script標簽

script標簽 用於 注解版本得動態SQL,官方示例如下

@Update({"<script>",
      "update Author",
      "  <set>",
      "    <if test='username != null'>username=#{username},</if>",
      "    <if test='password != null'>password=#{password},</if>",
      "    <if test='email != null'>email=#{email},</if>",
      "    <if test='bio != null'>bio=#{bio}</if>",
      "  </set>",
      "where id=#{id}",
      "</script>"})
    void updateAuthorValues(Author author);

2.9 sql , include標簽

sql 標簽是個sql片段,如下示例中將查詢條件抽出為一個sql片段,然后使用include標簽實現引用;我們要進行復用sql片段時就很有用,減少代碼量;

<sql id="condition">
        <where>
            <if test="customer_name!=null and customer_name!='' ">
                and `customer_name` = #{customer_name}
            </if>
            <if test="gender!=null and gender!=''">
                and `gender` = #{gender}
            </if>
        </where>
    </sql>
    <select id="getCustomer" resultType="com.zszxz.dynamic.entity.Customer" >
        select
            *
        from `customer`
        <include refid="condition">

        </include>

    </select>

2.10 bind標簽

bind 元素可以從 OGNL 表達式中創建一個變量並將其綁定到上下文;使用bind標簽好處就是在數據庫替換過程中可以除去不同數據庫語法得影響;如下示例中就可以實現在mysql,oracle,postgresql 中數據替換;如果使用 mysql 得concat 函數在oracle中不再適用;

 <sql id="condition">
        <where>
            <if test="customer_name!=null and customer_name!='' ">
                and customer_name like #{customer_name}
            </if>
            <if test="gender!=null and gender!=''">
                and gender = #{gender}
            </if>
        </where>
    </sql>
    <select id="getCustomer" resultType="com.zszxz.dynamic.entity.Customer" >
        <bind name="customer_name" value="'%'+customer_name+'%'"/>
        select
            *
        from customer
        <include refid="condition">

        </include>

    </select>

三 源碼

如果是初學者,有些地方看不懂可以查閱作者得mybatis 專欄說明有源碼地址,源碼中每個示例都有齊全得代碼提供個人學習;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM