zoukankan      html  css  js  c++  java
  • Mybatis对oracle数据库进行foreach批量插入操作

    MySQL支持的语法

    INSERT INTO `tableX` (
        `a`,
        `b`,
        `c`,
        `d`,
        `e`
        ) VALUES 
        <foreach collection ="list" item="param" index= "index" separator =",">
        (
          param.a,
          param.b,
          param.c,
          param.d,
          param.e
        )
        </foreach>

    oracle语法

    insert into tableX
    (a,b,c) 
    select * from (
    select 1,2,3 from dual
    union
    select 4,5,6 from dual
    ) t

    在使用mybatis时,oracle需要写成下面格式

    <foreach collection="list" item="file" index="index" separator="UNION">

    最近做一个批量导入的需求,将多条记录批量插入数据库中。解决思路:在程序中封装一个List集合对象,然后把该集合中的实体插入到数据库中,因为项目使用了MyBatis,所以打算使用MyBatis的foreach功能进行批量插入。期间遇到了“SQL 命令未正确结束 ”的错误,最终解决,记录下来供以后查阅和学习。

            首先,在网上参考了有关Mybatis的foreach insert的资料,具体如下:

            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

            然后,照葫芦画瓢写了如下的xml文件,

    xxxMapper.xml文件:

    <insert id="addSupCity" parameterType="java.util.List">
        <selectKey keyProperty="cityId" order="BEFORE" resultType="String">
            <![CDATA[SELECT SEQ_OCL_SUPCITY.NEXTVAL FROM dual]]>
        </selectKey>
        INSERT INTO T_OCL_SUPCITY
        (CITY_ID,CITY_CODE, CITY_NAME, AREA_DESC, SUP_ID, STAT)
        VALUES 
        <foreach collection="list" item="item" index="index" separator=",">     
          (
            #{item.cityId,jdbcType=VARCHAR},
            #{item.cityCode,jdbcType=VARCHAR},
            #{item.cityName,jdbcType=VARCHAR},
            #{item.areaDesc,jdbcType=VARCHAR},
            #{item.supId,jdbcType=VARCHAR},
            #{item.stat,jdbcType=VARCHAR}
          )
        </foreach>
    </insert>

            但是运行起来后就一直报错,报错信息如下:

    ### SQL: INSERT INTO T_OCL_SUPCITY
    (CITY_ID,CITY_CODE, CITY_NAME, AREA_DESC, SUP_ID, STAT) VALUES (?,?,?,?,?),(?,?,?,?,?)
    ### Cause: java.sql.SQLSyntaxErrorException: ORA-00933: SQL 命令未正确结束

            把SQL复制出来在PL/SQL中运行也是报同样的错,如上也可以看出,使用批量插入执行的SQL语句等价于: INSERT INTO T_OCL_SUPCITY (CITY_ID,CITY_CODE, CITY_NAME, AREA_DESC, SUP_ID, STAT) VALUES (?,?,?,?,?),(?,?,?,?,?),而在oracle中用insert into xxx values (xxx,xxx),(xxx,xxx) 这种语法是通不过的 。再回过头去看那篇文章,发现这是适用于MySQL的,不适用于Oracle,因此把xml文件修改一下:

    <insert id="addSupCity" parameterType="java.util.List">
          INSERT INTO T_OCL_SUPCITY
      (CITY_ID,CITY_CODE, CITY_NAME, AREA_DESC, SUP_ID, STAT)
    SELECT SEQ_OCL_SUPCITY.NEXTVAL CITY_ID, A.*
    FROM(
    <foreach collection="list" item="item" index="index" separator="UNION ALL">
     SELECT 
           #{item.cityCode,jdbcType=VARCHAR} CITY_CODE,
           #{item.cityName,jdbcType=VARCHAR} CITY_NAME,
           #{item.areaDesc,jdbcType=VARCHAR} AREA_DESC,
           #{item.supId,jdbcType=VARCHAR} SUP_ID,
           #{item.stat,jdbcType=VARCHAR} STAT
         FROM dual
       </foreach>
       )A
      </insert>

            运行通过。在Oracle的版本中,有几点需要注意的:

            1.SQL中没有VALUES;

            2.<foreach>标签中的(selece ..... from dual);

            3.<foreach>标签中的separator的属性为"UNION ALL",将查询合并结果集。

  • 相关阅读:
    读《大道至简》第二章有感
    读大道至简之感
    C#学习笔记二:并行编程基础:在 PLINQ 和 TPL 中的 Lambda 表达式
    C#学习笔记一:委托、匿名函数、Lambda 表达式
    VS2013 最常用 和 不是最常用的快捷键备忘
    EntityFramework初上手
    C#的值类型,引用类型,栈,堆,ref,out
    python批量下载图片
    django部署for新浪SAE
    Linux下安装搜狗拼音输入法
  • 原文地址:https://www.cnblogs.com/azhqiang/p/8136151.html
Copyright © 2011-2022 走看看