mybatis执行批量插入insert和批量更新update - yoodb - 素文宅博客

Mybatis批量插入和批量更新数据的资料相信大家从网上能查找到很多资料,本文重点总结一下mybatis执行批量插入insert和批量更新update数据。在mysql数据库中批量插入,如:insert into ... values (),(),...语法;而在oracle数据库中批量插入如:insert into selcect ... union all select ...语法。

mysql批量插入

<insert id="addRoleModule" parameterType="java.util.List">
    INSERT INTO T_P_ROLE_MODULE (ROLE_ID, MODULE_ID)
    VALUES <foreach collection="list" item="item" index="index"  
    separator=",">  
    ( #{item.roleId}, #{item.moduleId})  
    </foreach>  
</insert>

oracle批量插入

<insert id="addRoleModule" parameterType="java.util.List">
    INSERT INTO T_P_ROLE_MODULE (ROLE_ID, MODULE_ID)
    <foreach collection="list" item="item" index="index" separator=" UNION ALL ">  
    SELECT #{item.roleId}, #{item.moduleId} FROM DUAL
    </foreach>  
</insert>

如果传入多个参数时需要把它们封装成一个Map了,当然单参数也可以封装成map,实际上如果在传入参数的时候,在breast里面也是会把它封装成一个Map的,map的key就是参数名,所以collection属性值就是传入的List或array对象封装的map里面的key值。

测试这种方式可行性并插入指定序列,参考配置如下:

    <foreach collection="list" item="item" index="index" separator=" UNION ALL ">  
          SELECT SEQ_XXX.NEXTVAL , #{item.roleId}, #{item.moduleId} FROM DUAL
    </foreach>

报ORA-02287: sequence number not allowed here错误异常。ORA-02287错误网上最多的例子就是序列不能跟group by一起使用,解决方法就是把group by语句包起来,外层再select序列就可以了。目前这个错误显示不是group by的问题,也有神似大仙的人物建议使用oracle的insert all,可这个是将数据插入多张表的语句,与当前问题不属于同一范畴。在一个wiki里看到ORA-02287错误的详细描述:http://www.orafaq.com/wiki/ORA-02287

The following are the cases where you can't use a sequence:
For a SELECT Statement:
In a WHERE clause
In a GROUP BY or ORDER BY clause
In a DISTINCT clause
Along with a UNION or INTERSECT or MINUS
In a sub-query
Other areas:
A sub-query of Update or Delete
In a View or snapshot
In a DEFAULT or CHECK Condition of a table definition
Within a single SQL statement that uses CURRVAL or NEXTVAL, all referenced LONG columns, updated tables, 
and locked tables must be located on the same database.

其中讲到union中也不用使用序列。UNION 指令的目的是将两个 SQL 语句的结果合并起来,可以查看你要的查询结果. UNION在进行表链接后会筛选掉重复的记录,所以在表链接后会对所产生的结果集进行排序运算,删除重复的记录再返回结果。 UNION ALL的用法和union一样,只不过union含有distinct的功能,它会把两张表了重复的记录去掉,而union all不会,所以从效率上,union all 会高一点。

这里就是union中不能使用序列的问题,将select序列语句再往里包一层也是不行的,union会嵌套向里层检查。往里包不行,就往外包,写成这样可行

select SEQ_XXX.NEXTVAL, a.* from
(select 1,'66' from dual union
select 2,'77' from dual) a

于是foreach的配置可以修改成如下:

    <foreach collection="list" item="item" index="index" separator="union all" 
            open="select SEQ_XXX.NEXTVAL, a.* from (" close=") a">
      select #{item.code,jdbcType=VARCHAR}, #{item.name,jdbcType=VARCHAR} from dual
    </foreach>

参考资料:http://ljhzzyx.blog.163.com/blog/static/38380312201353536375,在mybatis配置中oracle和mysql数据库批量更新update也是有很大的不同之处:

mysql批量更新

mysql数据库采用一下写法即可执行,但是数据库连接必须配置:&allowMultiQueries=true,如:jdbc:mysql://blog.yoodb.com:3306/test?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true

<update id="batchUpdate" parameterType="java.util.List">
  <foreach collection="list" item="item" index="index" open="" close="" separator=";">
update test <set> test=${item.test}+1 </set> where id = ${item.id}
 </foreach>
</update>

oracle批量更新

<update id="batchUpdate"  parameterType="java.util.List">
   <foreach collection="list" item="item" index="index" open="begin" close="end;" separator=";">
update test <set> test=${item.test}+1 </set> where id = ${item.id}
   </foreach> 
</update>

Mybatis中sql配置文件属性参数含义说明,参考图:

1500620131.png

对于foreach标签的解释参考了网上的资料,具体如下:

foreach的主要用在构建in条件中,它可以在SQL语句中进行迭代一个集合,foreach元素的属性主要有 item,index,collection,open,separator,close。

item表示集合中每一个元素进行迭代时的别名,index指定一个名字,用于表示在迭代过程中,每次迭代到的位置,open表示该语句以什么开始,separator表示在每次进行迭代之间以什么符号作为分隔 符,close表示以什么结束,在使用foreach的时候最关键的也是最容易出错的就是collection属性,该属性是必须指定的,但是在不同情况 下,该属性的值是不一样的,主要有一下3种情况:

1. 如果传入的是单参数且参数类型是一个List的时候,collection属性值为list

2. 如果传入的是单参数且参数类型是一个array数组的时候,collection的属性值为array

3. 如果传入的参数是多个的时候,我们就需要把它们封装成一个Map了,当然单参数也可以封装成map


Original url: Access
Created at: 2019-08-27 21:54:45
Category: default
Tags: none

请先后发表评论
  • 最新评论
  • 总共0条评论