mybatis使用oracle和mysql批量插入、更新

MyBatis foreach语句批量插入数据

MyBatis的mapper配置文件的语句(在Oracle数据中,多条数据之间用union all 连接,MySQL数据库用,):

 <insert id="submitItem"  parameterType="java.util.List">
        insert into ITEM (
        ITEM_CODE,
        ITEM_NAME,
        ITEM_VALUE,
        ITEM_CATAGORY
        )
        select  item.* from
        (
        <foreach collection="list" item="item" index="index" separator="UNION ALL" >
            select
            #{item.itemCode,jdbcType=VARCHAR},
            #{item.itemName,jdbcType=VARCHAR},
            #{item.itemValue,jdbcType=VARCHAR},
            #{item.itemCategory,jdbcType=VARCHAR}
            from dual
        </foreach>
        ) item
    </insert>


<!--MySql写法-->
<insert id="submitItem"  parameterType="java.util.List">
    insert into ITEM (
    ITEM_CODE,
    ITEM_NAME,
    ITEM_VALUE,
    ITEM_CATAGORY
    )
    values
    <foreach collection="list" item="item" index="index" separator="," >
      (
        #{item.itemCode,jdbcType=VARCHAR},
        #{item.itemName,jdbcType=VARCHAR},
        #{item.itemValue,jdbcType=VARCHAR},
        #{item.itemCategory,jdbcType=VARCHAR}
     )
    </foreach>
</insert>

foreach元素解析:

foreach元素是一个遍历集合的循环语句,它支持遍历数组,List和Set接口的集合。

foreach元素中,collection是传进来的参数名称,可以是一个数组或者List、Set等集合;

                             item是循环中当前的元素(配置的item的名字随意取,类似于iterator);

                             index是当前元素在集合中的位置下标;

                             seperator是各个元素的间隔符;

                             ()分别是open和close元素,表示用什么符号将这些集合元素包装起来。 

注意:由于一些数据库的SQL对执行的SQL长度有限制,所以使用foreach元素的时候需要预估collection对象的长度;foreach除了用于本示例的循环插入,亦可用于构建in条件中(可自行尝试)。

或者:

package com.oracle.mapper;

import java.util.List;

import com.oracle.entity.AccountInfo;

public interface AccountInfoMapper {
    /**
     * 查询所有的数据
     * @return
     */
    List<AccountInfo> queryAllAccountInfo();
    
    /**
     * 批量插入数据
     * 
     * @param accountInfoList
     * @return
     */
    int batchInsertAccountInfo(List<AccountInfo> accountInfoList);
    
    /**
     * 批量插入数据,使用Oracle的序列获取唯一键
     * 
     * @param accountInfoList
     * @return
     */
    int batchInsertAccountInfoUseSeq(List<AccountInfo> accountInfoList);
    
    /**
     * 插入数据,使用Oracle的序列获取唯一键
     * 
     * @param accountInfoList
     * @return
     */
    int insertOne(AccountInfo accountInfo);
}


<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.oracle.mapper.AccountInfoMapper"><!--  接口的全类名 -->
    <!-- type:实体类的全类名 -->
    <resultMap id="BaseResultMap" type="com.oracle.entity.AccountInfo">
        <id column="ID" property="id" jdbcType="DECIMAL" />
        <result column="USERNAME" property="userName" jdbcType="VARCHAR" />
        <result column="PASSWORD" property="password" jdbcType="VARCHAR" />
        <result column="GENDER" property="gender" jdbcType="CHAR" />
        <result column="EMAIL" property="email" jdbcType="VARCHAR" />
        <result column="CREATE_DATE" property="createDate" jdbcType="DATE" />
    </resultMap>
    <!-- id 跟接口中的方法名称保持一致 -->
    <select id="queryAllAccountInfo" resultMap="BaseResultMap">
        select ID,
        USERNAME,PASSWORD,
        GENDER, EMAIL, CREATE_DATE from ACCOUNT_INFO
    </select>
    <insert id="batchInsertAccountInfo" parameterType="java.util.List">
        INSERT INTO ACCOUNT_INFO(ID, USERNAME,PASSWORD,GENDER, EMAIL,CREATE_DATE)
        (
        <foreach collection="list" index="" item="accountInfo"
            separator="union all">
            select
            #{accountInfo.id},
            #{accountInfo.userName},
            #{accountInfo.password},
            #{accountInfo.gender},
            #{accountInfo.email},
            #{accountInfo.createDate}
            from dual
        </foreach>
        )
    </insert>
    
    <insert id="batchInsertAccountInfoUseSeq" parameterType="java.util.List">
        <selectKey resultType="long" keyProperty="id" order="BEFORE"> 
            SELECT ACCOUNT_SEQ.NEXTVAL FROM dual
        </selectKey> 
        INSERT INTO ACCOUNT_INFO(ID, USERNAME,PASSWORD,GENDER, EMAIL,CREATE_DATE)
        SELECT ACCOUNT_SEQ.NEXTVAL, m.* FROM(
        <foreach collection="list" index="" item="accountInfo"
            separator="union all">
            select
            #{accountInfo.userName},
            #{accountInfo.password},
            #{accountInfo.gender},
            #{accountInfo.email},
            sysdate
            from dual
        </foreach>
        ) m
    </insert>
    
    <insert id="insertOne" parameterType="com.oracle.entity.AccountInfo">
        <selectKey resultType="long" keyProperty="id" order="BEFORE"> 
            SELECT ACCOUNT_SEQ.NEXTVAL FROM dual
        </selectKey> 
        INSERT INTO ACCOUNT_INFO(ID, USERNAME,PASSWORD,GENDER, EMAIL,CREATE_DATE)
        values(
            #{id},
            #{userName},
            #{password},
            #{gender},
            #{email},
            sysdate
        )
    </insert>
</mapper>

小礼物走一走,来简书关注我

 

 

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",将查询合并结果集。

 

 

Oracle+Mybatis的foreach insert批量插入这些坑的解决方案

2018年03月28日 16:19:23 guobinhui 阅读数 1668更多

所属专栏: web项目实战开发案例

 版权声明:本文为博主原创文章,如需转载,敬请注明转载链接 https://blog.csdn.net/guobinhui/article/details/79728971

最近做一个批量上传附件的需求,将多个附件的信息批量插入数据库中。解决思路:在程序中封装一个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

接下来我直接上代码  xxxMapper.xml文件:

 
  1. <insert id="insertVisitAttrs" parameterType="java.util.List">

  2. insert into HS_VISIT_ENCLOSURE

  3. (

  4. enc_id,

  5. vir_id,

  6. enc_type,

  7. del_status,

  8. enc_name,

  9. enc_size,

  10. save_path,

  11. create_emp,

  12. create_date,

  13. server_host,

  14. file_newName

  15. )

  16. values

  17. <foreach collection="list" item="item" index= "index" separator =",">

  18. (

  19. #{item.encId},

  20. #{item.virId},

  21. #{item.encType},

  22. #{item.delStatus},

  23. #{item.encName},

  24. #{item.encSize},

  25. #{item.savePath},

  26. #{item.createEmp},

  27. sysDate,

  28. #{item.serverHost},

  29. #{item.fileNewName}

  30. )

  31. </foreach>

  32. </insert>

遇到的问题:上传附件时,一次选择单个附件上传就没问题,一切正常,附件信息能正常保存到表里,But,一次选多个附件上传时,就会报下面的sql异常

[ERROR][2018-03-28 15:19:50,270][druid.sql.Statement]{conn-10005, pstmt-20007} execute error. insert into HS_VISIT_ENCLOSURE
    (   
        enc_id,
        vir_id,
        enc_type,
        del_status,
        enc_name,
        enc_size,
        save_path,
        create_emp,
        create_date,
        server_host,
        file_newName
    )
    values
      
    (
        ?,
        ?,
        ?,
        ?,
        ?,
        ?,
        ?,
        ?,
        sysDate,
        ?,
        ?
    )
     , 
    (
        ?,
        ?,
        ?,
        ?,
        ?,
        ?,
        ?,
        ?,
        sysDate,
        ?,
        ?
    )
java.sql.SQLSyntaxErrorException: ORA-00933: SQL 命令未正确结束

接着把sql复制出来,在pl/SQL里格式化一下,如下:

 
  1. insert into HS_VISIT_ENCLOSURE

  2. (enc_id,

  3. vir_id,

  4. enc_type,

  5. del_status,

  6. enc_name,

  7. enc_size,

  8. save_path,

  9. create_emp,

  10. create_date,

  11. server_host,

  12. file_newName)

  13. values

  14.  
  15. (?, ?, ?, ?, ?, ?, ?, ?, sysDate, ?, ?),

  16. (?, ?, ?, ?, ?, ?, ?, ?, sysDate, ?, ?)

看到这里立即发现了问题,原因就是因为批量插入insert into xxx values (xxx,xxx),(xxx,xxx) mysql是支持这种语法的,oracle不支持这种语法,那么把xml文件稍微修改一下:如下

 
  1. <insert id="insertVisitAttrs" parameterType="java.util.List">

  2. insert into HS_VISIT_ENCLOSURE

  3. (

  4. enc_id,

  5. vir_id,

  6. enc_type,

  7. del_status,

  8. enc_name,

  9. enc_size,

  10. save_path,

  11. create_emp,

  12. create_date,

  13. server_host,

  14. file_newName

  15. ) (

  16. <foreach collection="list" item="item" index= "index" separator ="UNION ALL">

  17. select

  18. #{item.encId} as encId,

  19. #{item.virId} as virId,

  20. #{item.encType} as encType,

  21. #{item.delStatus} as delStatus,

  22. #{item.encName} as encName,

  23. #{item.encSize} as encSize,

  24. #{item.savePath} as savePath,

  25. #{item.createEmp} as createEmp,

  26. sysDate as sysDate,

  27. #{item.serverHost} as serverHost,

  28. #{item.fileNewName} as serverHost

  29. from dual

  30. </foreach>

  31. )

  32. </insert>

    修改后重启项目,这次批量上传,运行通过。在Oracle的版本中批量insert操作,有几点需要注意的:

        1.SQL中没有VALUES;

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

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

 

 

170829、mybatis使用oracle和mybatis中批量更新

一、mybatis执行批量更新batch update 的方法(mysql数据库)

1、数据库连接必须配置:&allowMultiQueries=true(切记一定要加上这个属性,否则会有问题,切记!切记!切记!)
  我的配置如下:jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&amp;characterEncoding=UTF-8&amp;allowMultiQueries=true
2、批量修改并加判断条件(修改字段可选)

复制代码

<!-- 批量更新 -->
    <update id="updateMatchs" parameterType="java.util.List">
        <foreach collection="matchs" item="item" index="index" open="" close="" separator=";">
            update t_match
            <set>
                <if test="item.title !=null">
                    TITLE = #{item.title,jdbcType=VARCHAR},
                </if>
                <if test="item.homeScore !=null">
                    HOME_SCORE = #{item.homeScore,jdbcType=INTEGER},
                </if>
                <if test="item.visitScore !=null">
                    VISTT_SCORE = #{item.visitScore,jdbcType=INTEGER},
                </if>
                <if test="item.liveSource !=null">
                    LIVE_SOURCE = #{item.liveSource,jdbcType=VARCHAR},
                </if>
                <if test="item.liveURL !=null">
                    LIVE_URL = #{item.liveURL,jdbcType=VARCHAR},
                </if>
                <if test="item.isHotMatch !=null">
                    IS_HOT_MATCH = #{item.isHotMatch,jdbcType=VARCHAR}
                </if>
            </set>
        where HOME_TEAM_ID = #{item.homeTeamId,jdbcType=VARCHAR} and
        VISIT_TEAM_ID = #{item.visitTeamId,jdbcType=VARCHAR} and
        MATCH_TIME = #{item.matchTime,jdbcType=BIGINT}
        </foreach>
    </update>

复制代码

3、java 接口

复制代码

  /**
     * 批量修改赛程
     * 
     * @param matchs
     * @throws DaoException
     */
    void updateMatchs(@Param(value = "matchs")List<MatchBasic> matchs);

复制代码

二、mybatis执行批量更新batch update 的方法(oracle数据库)

1、批量修改并加判断条件(修改字段可选)

复制代码

<update id="batchUpdateSplitSinglePickCurrency" parameterType="java.util.List">
        <foreach collection="list" item="item" index="index" open="begin" close=";end;" separator=";">
            UPDATE ZC_TR_MULTI_ORDER_CURRENCY
            <set>
                <if test="item.sysCorderCode != null">
                    SYS_CORDER_CODE = #{item.sysCorderCode,jdbcType=VARCHAR},
                </if>

                <if test="item.sysPorderCode != null">
                    SYS_PORDER_CODE = #{item.sysPorderCode,jdbcType=VARCHAR},
                </if>

                <if test="item.bizPorderCode != null">
                    BIZ_PORDER_CODE = #{item.bizPorderCode,jdbcType=VARCHAR},
                </if>

                <if test="item.originalOrderCode != null">
                    ORIGINAL_ORDER_CODE = #{item.originalOrderCode,jdbcType=VARCHAR},
                </if>

                <if test="item.splitUserId != null">
                    SPLIT_USER_ID = #{item.splitUserId,jdbcType=VARCHAR},
                </if>

                <if test="item.createDate != null">
                    CREATE_DATE = #{item.createDate},
                </if>

                <if test="item.updateDate != null">
                    UPDATE_DATE = #{item.updateDate},
                </if>
            </set>
            where id = #{item.id,jdbcType=VARCHAR}
        </foreach>
    </update>

复制代码

2、java接口

  /**
     * @Desc :  批量更新大批量子订单详情信息
     * @Author : ZRP 
     * @Date : 2018/1/26 15:24
     */
    int batchUpdateSplitSinglePickCurrency(@Param(value = "list") List<MultiOrderCurrency> list) throws Exception;
PS:一定要注意文中标红色的地方,今天是我犯的错误,花了我20分钟了...

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值