[精] MySQL和Oracle下Mybatis批量操作示例和获取影响行数介绍

news/2023/6/7 0:29:07

手打不易,如果转摘,请注明出处!

注明原文:https://zhangxiaofan.blog.csdn.net/article/details/117933877


目录

前言

Mybatis 执行器

 表结构定义

Mybatis批量新增

批量新增——Mysql写法

批量新增——Oracle写法

Mybatis批量删除

批量删除——MySQL写法、Oracle写法一样

Mybatis批量更新

批量更新——MySQL写法

批量更新——Oracle写法

总结


前言

本文将以示例的方式,介绍Mybatsi批量操作增删改,以及如何获取影响行数,涉及到MySQL和Oracle两种不同的写法。

Mybatis 执行器

Mybatis 执行器三种模式介绍

default-executor-type:
simple(默认): SimpleExecutor, 单个 sqlsession 内, 每次操作,都开启一个 Statement 对象,用完立刻关闭 Statement 对象
batch: BatchExecutor, 单个 sqlsession 内,每次操作复用已有 Statement 对象, addBatch()汇总,然后统一执行executeBatch()因此 Mybatis 官方写明它无法返回行数(BATCH executor is in use, the update counts are being lost.)
reuse: ReuseExecutor, 应用实例内, 全局共享 Statement对象(Map<String, Statement>), 存在则复用

 表结构定义

CREATE TABLE `student`
(`id`   int(11) NOT NULL AUTO_INCREMENT,`name` varchar(255) DEFAULT NULL,`age`  int(11)      DEFAULT NULL,PRIMARY KEY (`id`)
)
ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci;

Mybatis批量新增

一般批量insert有4种写法
1.循环插入,每次插入一条,用的不多,这里不介绍

注意:如果是一次提交多个insert/update语句,MySQL的连接串需要加上
allowMultiQueries=true,表示开启批处理,可以执行批量SQL。就是多个分号;的SQL

2.BEGIN-END写法,这个是单次多条insert语句,用的不多,这里不介绍
3.foreach写法,这个是单次单条insert语句(常用)
4.JDBC原生写法,这个效率最高,不属于mybatis写法,这里不介绍

Mapper接口定义:

int insertListBatch(@Param("studentList") List<Student> studentList);

批量新增——Mysql写法

单次单条insert语句,foreach-batch写法

    <insert id="insertListBatch">insert into student(id,name,age) values<foreach collection="studentList" item="item" index="index" separator=",">(#{item.id,jdbcType=INTEGER},#{item.name,jdbcType=VARCHAR},#{item.age,jdbcType=INTEGER})</foreach></insert>

获取返回影响行数,只需要用下面这种执行器模式,直接获取返回值,该值就是影响行数。Oracle也是一样。

default-executor-type: simple
        int i = studentService.insertListBatch(studentList);logger.info("Mybatis SQL return :" + i);

批量新增——Oracle写法

单次单条insert语句,foreach-batch写法

    <insert id="insertListBatch">insert into STUDENT(ID,NAME,AGE)<foreach collection="studentList" item="item" index="index" separator="union all">(select#{item.id},#{item.name,jdbcType=VARCHAR},#{item.age,jdbcType=DECIMAL}from dual)</foreach></insert>

Oracle与MySQL批量插入的区别就是Oracle需要用到 union all 和 dual 关键字,看下Oracle批量插入的SQL示例就知道了:

INSERT INTO TEST.STUDENT (ID,NAME,AGE)
(SELECT 7,'change',18 FROM dual)
UNION ALL
(SELECT 5,'change',18 FROM dual)

上面说到,Mybatis批量插入有几种写法,那么这些写法有什么区别?效率怎么样?可以参考这篇文章:4亿数据批量操作插入,为什么不用Mybatis,而是选择原生JDBC?(文中有各类批量操作效率对比和总结)https://zhangxiaofan.blog.csdn.net/article/details/121351546


Mybatis批量删除

Mapper接口定义

int deleteByIdList(@Param("list") List<String> list);

批量删除——MySQL写法、Oracle写法一样

    <delete id="deleteByIdList">delete from studentwhere id IN<foreach collection="list" item="item" open="(" close=")" separator=",">#{item}</foreach></delete>

 返回影响行数,跟批量插入一样,用simple(默认)执行器即可,直接获取返回值。

Mybatis批量更新

Mapper接口定义

int updateListByIdBatch(@Param("studentList") List<Student> studentList);

批量更新——MySQL写法

    <update id="updateListByIdBatch">update student<trim prefix="set" suffixOverrides=","><trim prefix="age =case" suffix="end,"><foreach collection="studentList" item="item" index="index"><if test="item.age != null">when id=#{item.id} then #{item.age,jdbcType=INTEGER}</if></foreach></trim><trim prefix="name =case" suffix="end"><foreach collection="studentList" item="item" index="index"><if test="item.name != null">when id=#{item.id,jdbcType=INTEGER} then #{item.name,jdbcType=VARCHAR}</if></foreach></trim></trim>where id in<foreach collection="studentList" item="item" index="index" separator="," open="(" close=")">#{item.id,jdbcType=INTEGER}</foreach></update>

返回影响行数,跟批量插入一样,用simple(默认)执行器即可,直接获取返回值。 

批量更新——Oracle写法

​<update id="updateListByIdBatch">update STUDENT<trim prefix="set" suffixOverrides=","><trim prefix="AGE =case" suffix="end,"><foreach collection="studentList" item="item" index="index"><choose><when test="item.age != null">when ID=#{item.id} then #{item.age,jdbcType=DECIMAL}</when><otherwise><!-- 字段为null, 用原值更新(保留原值), 否则会被重置为null -->when ID=#{item.id,jdbcType=DECIMAL} then age</otherwise></choose></foreach></trim><trim prefix="NAME =case" suffix="end"><foreach collection="studentList" item="item" index="index"><choose><when test="item.name != null">when ID=#{item.id,jdbcType=DECIMAL} then #{item.name,jdbcType=VARCHAR}</when><otherwise><!-- 字段为null, 用原值更新(保留原值), 否则会被重置为null -->when ID=#{item.id,jdbcType=DECIMAL} then name</otherwise></choose></foreach></trim></trim>where ID in<foreach collection="studentList" item="item" index="index" separator="," open="(" close=")">#{item.id,jdbcType=DECIMAL}</foreach></update>​

Oracle与MySQL批量更新的写法主要区别在,Oracle需要用 choose-when-otherwise 来解决部分输入字段为null的问题。感兴趣的朋友可以参考这篇文章:

Oralce Mybaits批量更新的正确写法——解决传入字段为nullhttps://zhangxiaofan.blog.csdn.net/article/details/120179181?spm=1001.2014.3001.5502返回影响行数,跟批量插入一样,用simple(默认)执行器即可,直接获取返回值。

where如果有多个条件,可以写成类似这样的:

        where (ID,ID2) in<foreach collection="studentList" item="item" index="index" separator="," open="(" close=")">(#{item.id,jdbcType=DECIMAL},#{item.id2,jdbcType=DECIMAL})</foreach>

总结

上述Mybatis的批量操作都是一条SQL操作完成的,也是项目中常用到的写法。当一次操作的数据量很大的时候,这种写法效率会大大降低(可能都不如循环一条一条的执行)。因此实际项目过程中批量操作,如果数据较大,就要分批次处理,一次传一部分,具体传多少跟表字段大小和SQL条数相关。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.exyb.cn/news/show-4560811.html

如若内容造成侵权/违法违规/事实不符,请联系郑州代理记账网进行投诉反馈,一经查实,立即删除!

相关文章

我的2016—“不平凡”的一年

笔者介绍&#xff1a;姜雪伟&#xff0c;IT公司技术合伙人&#xff0c;IT高级讲师&#xff0c;CSDN社区专家&#xff0c;特邀编辑&#xff0c;畅销书作者&#xff0c;国家专利发明人;已出版书籍&#xff1a;《手把手教你架构3D游戏引擎》电子工业出版社和《Unity3D实战核心技术…

2016年的总结——离开创业潮的日子

刚好今天在写工作总结&#xff0c;就顺便在博客上写写了&#xff0c;顺便记录一下 2016这一年的总结 工作事件&#xff1a;1.融合SDK框架搭建2.聚合SDK 加入切支付流程3.聚合对接聚合的流程框架搭建4.制定工作流程5.开发.exe 多渠道打包工具&#xff08;市场、运营使用&#xf…

SpringMVC-基础入门

文章目录SpringMVC1&#xff0c;SpringMVC概述2&#xff0c;SpringMVC入门案例2.1 需求分析2.2 案例制作步骤1:创建Maven项目步骤2:补全目录结构步骤3:导入jar包步骤4:创建配置类步骤5:创建Controller类步骤6:使用配置类替换web.xml步骤7:配置Tomcat环境步骤8:启动运行项目步骤…

2016年,续航新能量

近两年写的文字越来越少了。这可能是个好事。前几年文字多&#xff0c;想得多&#xff0c;能做得少。不是不做&#xff0c;而是做不起来。而现在&#xff0c;尤其是2016年&#xff0c;确实是觉得自己的世界突然大了&#xff0c;手头的事情常是想到就能做&#xff0c;以致于有些…

2016年小结 2017年展望

转载请标明出处&#xff1a;http://blog.csdn.net/junzaivip/article/details/54231935&#xff0c;本文出自【junzaivip博客】 每个人的世界里有的不止是光鲜&#xff0c;其实还有更多别人看不到的悲催的一面。不论怎样&#xff0c;还是要无比精彩的走下去。一年了有必要进行总…

在2016年如何学习JavaScript?

在2016年如何学习JavaScript&#xff1f;原文链接 Want to learn JavaScript in 2016?作者&#xff1a;Vincent O译者&#xff1a;相信有不少人已经读过在 2016 年学 JavaScript 是一种什么样的体验&#xff1f;这篇神文&#xff0c;那么假如你真的要在2016年开始学习JavaScri…

2016年的不正式总结

摘要 上一次写个人年终总结还是2014年1月1日&#xff0c;写的2013年的总结。距今天已三年了&#xff0c;那时候的总结还是写在QQ空间里。之后的三年里面再也没有去总结了&#xff0c;早上醒来&#xff0c;玩完手机&#xff0c;不知为何想简单写点&#xff0c;因为今天是2016的…

双亲委派模型详解

双亲委派模型 双亲委派机制&#xff1a;保证安全 总体过程&#xff1a;1.类加载器收到类加载的请求&#xff0c;2.再将这个请求向上委托给父类加载器完成&#xff0c;一直向上委托&#xff0c;直到bootstrap类加载器&#xff0c;3.bootstrap加载器检查能否加载&#xff0c;能加…