Mybatis批量插入到MySQL和Oracle
MySQL
方式一:直接插入
<insert id="batchInsert">
insert target_table(column_a, column_b) values
<foreach item="item" index="index" collection="list" separator=",">
(#{item.columnA},#{item.columnB})
</foreach>
</insert>
方式二:批量更新(如果不存在则插入)
<insert id="batchUpdate">
INSERT INTO
target_table (column_a,column_b,column_c,column_key)
VALUES
<foreach item="item" index="index" collection="list" separator=",">
(#{item.columnA},#{item.columnB},#{item.columnC},#{item.columnKey})
</foreach>
ON DUPLICATE KEY UPDATE
column_a = VALUES(column_a),
column_b = VALUES(column_b),
column_c = VALUES(column_c),
column_d = VALUES(columnKey)
</insert>
说明:
- 此方式是根据表target_table的主键进行判断,如果出现主键冲突则更新数据,主键不存在就插入数据,所以必须保证表有设置主键
- 在上述的xml代码中列column_key可以视为主键
- 如果是单条数据根据主键更新则直接去掉标签即可
Oracle
方式一:直接插入
<insert id="batchInsert">
insert all
<foreach item="item" index="index" collection="list" separator=" ">
into target_table(column_a, column_b) values (#{item.columnA},#{item.columnB})
</foreach>
select 1 from dual
</insert>
注意:
- foreach中的separator分隔符为" ";
- 需要有select 1 from dual来使插入生效
- 在某些情况下需要显式指定标签中的useGeneratedKeys=“false”
方式二:批量更新(如果不存在则插入)
<insert id="batchUpdate" parameterType="EntityDemo">
MERGE INTO target_table t
USING (
<foreach item="item" index="index" collection="list" separator="union">
SELECT
#{item.id} id,
#{item.columnA} column_a,
#{item.columnB} column_b,
#{item.columnC} column_c,
sysdate column_date
FROM DUAL
</foreach>
) s
ON (t.id = s.id)
WHEN MATCHED THEN
UPDATE SET
t.column_a=s.column_a,
t.column_b=s.column_b,
t.column_c=s.column_c,
t.column_date=s.column_date
WHEN NOT MATCHED THEN
INSERT (id,column_a,column_b,column_c,column_date)
VALUES (s.id,s.column_a,s.column_b,s.column_c,s.column_date)
</insert>
说明:
-
标签中的separator分隔符为union
-
此方法是通过target_table的id列来判断是否存在数据,如果存在则更新,如果不存在则插入,与MySQL不同这里是显式指定的
-
此方法需要将待更新数据创建为一个临时表s,然后再将临时表中的数据更新到数据库或者插入到数据库
-
此方法中可以不对属性进行判空,如果属性为空那么临时的字段对应为空,可以直接通过临时表数据写入数据库
-
ON判断条件中可以指定多个字段,通过AND连接多个判断条件
-
插入时如果出现列类型不匹配的异常,可以在创建临时表时指定字段类型,例如:
SELECT #{item.id,jdcType=VARCHAR} id, #{item.columnA,jdcType=CHAR} column_a, #{item.columnB,jdcType=DECIMAL} column_b, #{item.columnC,jdcType=TIMESTAMP} column_c, sysdate column_date FROM DUAL