1. 程式人生 > >Mybatis結合Oracle的foreach insert批量插入

Mybatis結合Oracle的foreach insert批量插入

 最近做一個批量匯入的需求,將多條記錄批量插入資料庫中。解決思路:在程式中封裝一個List集合物件,然後把該集合中的實體插入到資料庫中,因為專案使用了MyBatis,所以打算使用MyBatis的foreach功能進行批量插入。期間遇到了“SQL 命令未正確結束 ”的錯誤,最終解決,記錄下來供以後查閱和學習。

        首先,在網上參考了有關Mybatis的foreach insert的資料,具體如下:

        foreach的主要用在構建in條件中,它可以在SQL語句中進行迭代一個集合。

        foreach元素的屬性主要有 item,index,collection,open,separator,close。

        item表示集合中每一個元素進行迭代時的別名,index指定一個名字,用於表示在迭代過程中,每次迭代到的位置,open表示該語句以什麼開始,separator表示在每次進行迭代之間以什麼符號作為分隔符,close表示以什麼結束,在使用foreach的時候最關鍵的也是最容易出錯的就是collection屬性,該屬性是必須指定的,但是在不同情況 下,該屬性的值是不一樣的,主要有一下3種情況:

        1.如果傳入的是單引數且引數型別是一個List的時候,collection屬性值為list

        2.如果傳入的是單引數且引數型別是一個array陣列的時候,collection的屬性值為array

        3.如果傳入的引數是多個的時候,我們就需要把它們封裝成一個Map了,當然單引數也可以封裝成map

        然後,照葫蘆畫瓢寫了如下的xml檔案,

xxxMapper.xml檔案:

<insert id="addSupCity" parameterType="java.util.List">
    <selectKey keyProperty="cityId" order="BEFORE" resultType="String">
        <![CDATA[SELECT SEQ_OCL_SUPCITY.NEXTVAL FROM dual]]>
    </selectKey>
    INSERT INTO T_OCL_SUPCITY
    (CITY_ID,CITY_CODE, CITY_NAME, AREA_DESC, SUP_ID, STAT)
    VALUES 
    <foreach collection="list" item="item" index="index" separator=",">     
      (
        #{item.cityId,jdbcType=VARCHAR},
        #{item.cityCode,jdbcType=VARCHAR},
        #{item.cityName,jdbcType=VARCHAR},
        #{item.areaDesc,jdbcType=VARCHAR},
        #{item.supId,jdbcType=VARCHAR},
        #{item.stat,jdbcType=VARCHAR}
      )
    </foreach>
</insert>

        但是執行起來後就一直報錯,報錯資訊如下:

### SQL: INSERT INTO T_OCL_SUPCITY
(CITY_ID,CITY_CODE, CITY_NAME, AREA_DESC, SUP_ID, STAT) VALUES (?,?,?,?,?),(?,?,?,?,?)
### Cause: java.sql.SQLSyntaxErrorException: ORA-00933: SQL 命令未正確結束

        把SQL複製出來在PL/SQL中執行也是報同樣的錯,如上也可以看出,使用批量插入執行的SQL語句等價於: INSERT INTO T_OCL_SUPCITY (CITY_ID,CITY_CODE, CITY_NAME, AREA_DESC, SUP_ID, STAT) VALUES (?,?,?,?,?),(?,?,?,?,?),而在oracle中用insert into xxx values (xxx,xxx),(xxx,xxx) 這種語法是通不過的 。再回過頭去看那篇文章,發現這是適用於MySQL的,不適用於Oracle,因此把xml檔案修改一下:

<insert id="addSupCity" parameterType="java.util.List">
      INSERT INTO T_OCL_SUPCITY
  (CITY_ID,CITY_CODE, CITY_NAME, AREA_DESC, SUP_ID, STAT)
SELECT SEQ_OCL_SUPCITY.NEXTVAL CITY_ID, A.*
FROM(
<foreach collection="list" item="item" index="index" separator="UNION ALL">
 SELECT 
       #{item.cityCode,jdbcType=VARCHAR} CITY_CODE,
       #{item.cityName,jdbcType=VARCHAR} CITY_NAME,
       #{item.areaDesc,jdbcType=VARCHAR} AREA_DESC,
       #{item.supId,jdbcType=VARCHAR} SUP_ID,
       #{item.stat,jdbcType=VARCHAR} STAT
     FROM dual
   </foreach>
   )A
  </insert>

        執行通過。在Oracle的版本中,有幾點需要注意的:

        1.SQL中沒有VALUES;

        2.<foreach>標籤中的(selece ..... from dual);

        3.<foreach>標籤中的separator的屬性為"UNION ALL",將查詢合併結果集。