需求
示例:很普通的需求
表結構:
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,這樣就很清楚了。