1. 程式人生 > >mybatis使用foreach批次插入,解決sequence只查詢一次的問題(在此,我只看union all 部分)

mybatis使用foreach批次插入,解決sequence只查詢一次的問題(在此,我只看union all 部分)

oracle的批量插入方式是:
insert  into db(id, zgbh, shbzh)
        select '1', '2', '3' from dual
        union all select '2', '3', '4' from dual
        union all select '3', '4', '5' from dual
        union all select '4', '5', '6' from dual
        union all select '5', '6', '7' from dual

由於專案使用到sequence生成id,剛開始的寫法:
<!-- 批次插入,List-->
     <insert id="insertList" useGeneratedKeys="true" parameterType="java.util.List">
        <selectKey resultType="long" keyProperty="id"
order="BEFORE">
            SELECT SEQ_xxx_DETAIL.NEXTVAL FROM DUAL
        </selectKey>
         insert into TBL_xxx_DETAIL
              (
                 <include refid="allColumns"/>
              )
              <foreach collection="list" item="item" index="index"  separator="UNION ALL" >
                  SELECT
                 #{id, jdbcType=NUMERIC javaType=long},

                 #{item.batchFundTitleId, jdbcType=NUMERIC javaType=long},
                 #{item.transactionRequestId, jdbcType=NUMERIC javaType=long},
                 #{item.arAmt, jdbcType=DECIMAL javaType=java.math.BigDecimal},
                 #{item.bankServiceAmt, jdbcType=DECIMAL javaType=java.math.BigDecimal},
                 #{item.receivedAmt, jdbcType=DECIMAL javaType=java.math.BigDecimal},
                 #{item.realReceivedAmt, jdbcType=DECIMAL javaType=java.math.BigDecimal},
                 #{item.verifyDate, jdbcType=DATE javaType=date},
                 #{item.verifyOp, jdbcType=VARCHAR javaType=string},
                 #{item.verifyStatus, jdbcType=INTEGER javaType=int},
                 #{item.created, jdbcType=VARCHAR javaType=string},
                 #{item.createdDate, jdbcType=DATE javaType=date},
                 #{item.createdIp, jdbcType=VARCHAR javaType=string},
                 #{item.modified, jdbcType=VARCHAR javaType=string},
                 #{item.modifiedDate, jdbcType=DATE javaType=date},
                 #{item.modifiedIp, jdbcType=VARCHAR javaType=string}
                  from dual
             </foreach>
     </insert>
這樣的寫法sequence的查詢方法只查詢一次,造成list中的物件的再插入時id都會一樣,違反主鍵的唯一性約束。

所以修改為如下的形式:
<insert id="insertList" useGeneratedKeys="true" parameterType="java.util.List">
        <selectKey resultType="long" keyProperty="id" order="BEFORE">
            SELECT SEQ_xxx_DETAIL.NEXTVAL FROM DUAL
        </selectKey>

         insert into TBL_xxx_DETAIL
              (
                 <include refid="allColumns"/>
              ) select  SEQ_xxx_DETAIL.NEXTVAL,A.*  from(
              <foreach collection="list" item="item" index="index"  separator="UNION ALL" >
                  SELECT
                 #{item.batchFundTitleId, jdbcType=NUMERIC javaType=long},
                 #{item.transactionRequestId, jdbcType=NUMERIC javaType=long},
                 #{item.arAmt, jdbcType=DECIMAL javaType=java.math.BigDecimal},
                 #{item.bankServiceAmt, jdbcType=DECIMAL javaType=java.math.BigDecimal},
                 #{item.receivedAmt, jdbcType=DECIMAL javaType=java.math.BigDecimal},
                 #{item.realReceivedAmt, jdbcType=DECIMAL javaType=java.math.BigDecimal},
                 #{item.verifyDate, jdbcType=DATE javaType=date},
                 #{item.verifyOp, jdbcType=VARCHAR javaType=string},
                 #{item.verifyStatus, jdbcType=INTEGER javaType=int},
                 #{item.created, jdbcType=VARCHAR javaType=string},
                 #{item.createdDate, jdbcType=DATE javaType=date},
                 #{item.createdIp, jdbcType=VARCHAR javaType=string},
                 #{item.modified, jdbcType=VARCHAR javaType=string},
                 #{item.modifiedDate, jdbcType=DATE javaType=date},
                 #{item.modifiedIp, jdbcType=VARCHAR javaType=string}
                  from dual
             </foreach>) A
     </insert>
把foreach中的id去掉,foreach拼出來的資料作為一張表A,然後從表A中查詢資料,再接上從sequence中讀取的值作為id。這樣sequence的值就會多次讀取,id就會不一樣。
<selectKey resultType="long" keyProperty="id" order="BEFORE">
            SELECT SEQ_xxx_DETAIL.NEXTVAL FROM DUAL
        </selectKey>
刪除後會報錯:SQL command not properly ended,暫時沒有查出來原因,有知道的原因的請告訴我哈。
以此文拋磚引玉吧,希望能有更合適的方式。

mysql的批量插入如下:
INSERT INTO MyTable(ID,NAME) VALUES(7,'003'),(8,'004'),(9,'005')
而且mysql有自增欄位,可以把id設定為自增的,這樣的話就不存在id一致的情況。

<insert id="insertBatch" > 
    insert into student ( NAME,SEX,ADDRESS,TELEPHONE,TID)  
    values  
    <foreach collection="list" item="item" index="index" open="(" separator=","  close=")"> 
         #{item.name},
         #{item.sex},
         #{item.address},
         #{item.telephone},
         #{item.tId} 
    </foreach> 
</insert>