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,这样就很清楚了。

猜你喜欢

转载自blog.csdn.net/x763795151/article/details/107049626
今日推荐