oracle+mybatis批量插入的兩種常規寫法

需求

示例:很普通的需求

表結構:

create table t_user(
  user_id varchar2(20),
  user_name varchar2(20)
);

java bean:

public class User {
    String userId;
    String userName;
    // ...
}

現在有一個List<User>對象插入到t_user表裏,oracle數據庫,mybatis框架,使用批量插入方式。

實現

寫法不固定,我這樣寫的,僅作參考

多表插入

    <insert id="batchSave" parameterType="com.xuxd.bean.User">
        insert all
        <foreach collection="list" item="user" separator="  " open=" " close=" " index="index">
            into t_user(
            user_id,
            user_name
            ) VALUES (
            #{user.userId},
            #{user.userName}
            )
        </foreach>
        select 1 from dual
    </insert>

單表插入

    <insert id="batchSave" parameterType="com.xuxd.bean.User">
        insert into t_user(user_id, user_name)
        select u.id, u.name from
        (
            <foreach collection="list" index="index" item="user" open=" " close=" " separator=" union all ">
                select #{user.userId} as id, #{user.userName} as name from dual
            </foreach>
        ) u
    </insert>

說明

這兩種寫法很常見(細節上可能不同),在網上一搜就出來了,大多類似,對於初學者可能好奇爲何這樣寫,解釋下。

下面參考了官方文檔,SQL Language Reference11g Release 2 (11.2)

看下插入語法:

單表插入和多表插入,按前面的順序解釋

多表插入

根據當前場景主要是上面紅框內,無條件多表插入。

insert all into t1(...) values (...) into t2(...) values(...) ... select ... from t

意思是向t1、t2...等多個表中插入數據,後面注意跟了個子查詢select ... from t。這個子查詢的結果前面是可以用的。but,重點是這個子查詢的結果行數用來計算前面插入的每個表的行數。所以,如果子查詢返回多行,前面每個表就會插入多行,對於返回的每一行,每個表都要執行一次插入。如果是0行,前面每個表都不會插入。

因此,當前場景的mybatis寫法實現是,插入的多個表都是同一個表,然後select 1 from dual返回的行數是1,每個表就只插入1行。

順便提一下,如果需要每行id是一個序列生成的,這種情況,就不能這樣寫了,因爲這條語句,會被看做一條sql,所以如果需要生成序列,那麼每列的序列值都是同一個值。

單表插入

單表插入,這裏實現其實就是一個子查詢,查詢是借用dual表返回結果,可以看下子查詢語法:

每一個子查詢:select #{user.userId} as id #{user.userName} as name from dual使用union all,這樣就很清楚了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章