Mybatis對oracle數據庫進行foreach批量插入操作


MySQL支持的語法

INSERT INTO `tableX` (
    `a`,
    `b`,
    `c`,
    `d`,
    `e`
    ) VALUES 
    <foreach collection ="list" item="param" index= "index" separator =",">
    (
      param.a,
      param.b,
      param.c,
      param.d,
      param.e
    )
    </foreach>

oracle語法

insert into tableX
(a,b,c) 
select * from (
select 1,2,3 from dual
union
select 4,5,6 from dual
) t

在使用mybatis時,oracle需要寫成下面格式

<foreach collection="list" item="file" index="index" separator="UNION">

 

最近做一個批量導入的需求,將多條記錄批量插入數據庫中。解決思路:在程序中封裝一個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",將查詢合並結果集。


免責聲明!

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



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