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文件:
-
<insert id="insertVisitAttrs" parameterType="java.util.List">
-
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
-
<foreach collection="list" item="item" index= "index" separator =",">
-
(
-
#{item.encId},
-
#{item.virId},
-
#{item.encType},
-
#{item.delStatus},
-
#{item.encName},
-
#{item.encSize},
-
#{item.savePath},
-
#{item.createEmp},
-
sysDate,
-
#{item.serverHost},
-
#{item.fileNewName}
-
)
-
</foreach>
-
</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里格式化一下,如下:
-
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, ?, ?)
看到这里立即发现了问题,原因就是因为批量插入insert into xxx values (xxx,xxx),(xxx,xxx) mysql是支持这种语法的,oracle不支持这种语法,那么把xml文件稍微修改一下:如下
-
<insert id="insertVisitAttrs" parameterType="java.util.List">
-
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
-
) (
-
<foreach collection="list" item="item" index= "index" separator ="UNION ALL">
-
select
-
#{item.encId} as encId,
-
#{item.virId} as virId,
-
#{item.encType} as encType,
-
#{item.delStatus} as delStatus,
-
#{item.encName} as encName,
-
#{item.encSize} as encSize,
-
#{item.savePath} as savePath,
-
#{item.createEmp} as createEmp,
-
sysDate as sysDate,
-
#{item.serverHost} as serverHost,
-
#{item.fileNewName} as serverHost
-
from dual
-
</foreach>
-
)
-
</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&characterEncoding=UTF-8&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分钟了...