【MyBatis-4】MyBatis批量insert、update、delete数据
前言
在日常开发中,批量操作数据库数据是常见场景,比如批量插入、批量修改、批量删除数据。MyBatis为批量操作数据提供了非常便利的方案。
当然,也可以在程序中自己拼接sql语句,在dao层传入该sql语句作为参数。要注意的是,采用这种方式时,不能使用 #
而是要使用 $
。
批量操作需要使用到比较复杂的标签,所以都在 xml
中实现。
需要注意的是,数据库配置中要将allowMultiQueries
置为true
,例如:
jdbc:mysql://localhost:3306?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false
1 批量insert
首先,看一下批量插入的xml
样板写法:
<insert id="addStudentBatch">
INSERT INTO mutest.student(id,name)
VALUES
<foreach collection="studentList" item="student" separator=",">
(#{student.id},#{student.name})
</foreach>
</insert>
上面实现了向 student表中批量插入student信息。
这个很简单,只要调用时,传入学生实体的list就可以了。
dao层:
int addStudentBatch(JSONArray studentList);
studentList的数据样板:
[
{
"id": 1,
"name": "爱因斯坦"
},
{
"id": 2,
"name": "法拉第"
},
{
"id": 1,
"name": "莱布尼兹"
}
]
1.1 根据一个主键批量插入
再看一个稍微复杂一些的场景,向年级表插入班级学生关联信息。表结构如下:
id |
class_id |
student_id |
---|---|---|
1 |
1 |
1 |
1 |
1 |
2 |
数据结构如下(JOSNObject student):
{
"id": 1,
"data": [
{
"classId": 1,
"studentId": 1
},
{
"classId": 1,
"studentId": 2
},{
"classId": 1,
"studentId": 3
}
]
}
与之对应的dao层(位于StudentDao.java中):
int addGradeStudentBatch(Long gradeId, JSONArray studentList);
service层:
Long gradeId = student.getLong("id");
JSONArray sutdnetList = student.getJSONArray("data");
studentDao.addGradeStudentBatch(gradeId,sutdnetList);
xml:
<insert id="addGradeStudentBatch">
INSERT INTO mutest.grade_student(gradeId,class_id,student_id)
VALUES
<foreach collection="studentList" item="student" separator=",">
(#{gradeId},#{student.classId},#{student.studentId})
</foreach>
</insert>
1.2 插入已存在数据自动更新
首先,已存在数据的判定由数据库通过唯一的主键或者索引实现的。
以上文向年级表插入班级学生关联信息为例,因为通过三个字段才能断定一条数据是否已存在,所以首先要将为这三个字段添加联合唯一索引:
alter table mutest.grade_student add unique index(id,class_id,student_id);
接下来只要在 xml 中略作修改即可:
<insert id="addGradeStudentBatch">
INSERT INTO mutest.grade_student(gradeId,class_id,student_id)
VALUES
<foreach collection="studentList" item="student" separator=",">
(#{gradeId},#{student.classId},#{student.studentId})
</foreach>
on duplicate key update
id = values(id),
class_id = values(class_id),
student_id = values(student_id)
</insert>
2 批量update
student表是这样子的:
id |
name |
age |
---|---|---|
1 |
zhangsan |
17 |
2 |
lisi |
18 |
3 |
wangwu |
17 |
待更新的数据:
{
"data": [
{
"id": 1,
"name": "zhangsan2",
"age": 20
},
{
"id": 2,
"name": "lisi2",
"age": 21
}
]
}
dao层:
void updateStudentBatch(JSONArray studentList);
2.1 MultiQueries
所谓的MultiQueries
,就是一次提交多个查询语句。采用这种方式,要设置 allowMultiQueries=true
。
首先,我们来看看这种方式下,sql是怎么写的:
UPDATE mutest.student set name='zhangsan2',age=20 WHERE id=1;
UPDATE mutest.student set name='lisi2',age=21 WHERE id=2;
其实很简单,就是逐条更新,但一次提交给MySQL服务器而已。
mybatis xml中的写法如下:
<update id="updateStudentBatch" parameterType="java.util.List">
<foreach collection="list" item="item" index="index">
UPDATE mutest.student
<set>
<if test="item.name != null">
name=#{item.name},
</if>
<if test="item.age != null">
age=#{item.age}
</if>
</set>
WHERE
id=#{item.id};
</foreach>
</update>
控制台sql语句:
Preparing: UPDATE mutest.student SET name=?, age=? WHERE id=?; UPDATE mutest.student SET name=?, age=? WHERE id=?;
Parameters: zhangsan2(String), 20(Integer), 1(Integer), lisi2(String), 21(Integer), 2(Integer)
Updates: 1
2.2 case when
这个思路是借用 case when语法 拼接语句来实现批量更新。要想实现将待更新的数据更新到库里,sql语句该怎么写呢,如下:
UPDATE mutest.student
SET name = CASE id
WHEN 1 THEN 'zhangsan2'
WHEN 2 THEN 'lisi2'
END,
age = CASE id
WHEN 1 THEN 20
WHEN 2 THEN 21
END
WHERE id IN (1,2)
**mybatis xml中的写法如下:**du
<update id="updateStudentBatch" parameterType="java.util.List">
UPDATE mutest.student
<trim prefix="SET" suffixOverrides=",">
<trim prefix="name =CASE" suffix="END,">
<foreach collection="list" item="item" index="index">
<if test="item.name != null">
WHEN id=#{item.id} THEN #{item.name}
</if>
</foreach>
</trim>
<trim prefix="age =CASE" suffix="END,">
<foreach collection="list" item="item" index="index">
<if test="item.age != null">
WHEN id=#{item.id} THEN #{item.age}
</if>
</foreach>
</trim>
</trim>
WHERE id IN
<foreach collection="list" index="index" item="item" separator="," open="(" close=")">
#{item.id,jdbcType=BIGINT}
</foreach>
</update>
控制台sql语句:
Preparing: UPDATE mutest.student SET name =CASE WHEN id=? THEN ? WHEN id=? THEN ? END, age =CASE WHEN id=? THEN ? WHEN id=? THEN ? END WHERE id IN ( ? , ? )
Parameters: 1(Integer), zhangsan2(String), 2(Integer), lisi2(String), 1(Integer), 20(Integer), 2(Integer), 21(Integer), 1(Integer), 2(Integer)
Updates: 2
未完待续…
- 【自然框架】开源社区活动,会员注册的第一份代码!
- CentOS 7 安装Mono 和 MonoDevelop
- 【自然框架】注册会员活动——第一份代码的修改建议(第一版)
- 【视频】自然框架之分页控件的使用方法(一) PostBack方式的一般分页方式
- Java中的Socket编程学习
- 【视频】自然框架之分页控件的使用方法(二) 下载、DLL说明和web.config的设置
- Jsp开发中遇到的中文乱码问题及解决方法
- 开发中最常见的Java字符串问题总结
- .net异步性能测试(包括ASP.NET MVC WebAPI异步方法)
- Java 8的函数式编程学习
- 在C++中反射调用.NET(一) 反射调用第一个.NET类的方法
- QuickPager分页控件,最简单的设置代码
- Java中有关Null的9问题
- 在C++中反射调用.NET(二) 定义数据接口 绑定委托方法 使用SOD DTO 对象 将.NET对象转换到C++结构体为何不使用序列化的问题
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释