Mybatis入门之实现简单批量插入(insert)、删除(delete)、更新(update)
插入和删除很简单,而更新有很多不同的情景
我的表结构:
插入和删除
mapper的xml映射文件,直接放代码套了就能用,BookVO中有一个books集合存放数据:
<!-- 实现批量插入 --> <insert id="insertBooksBatch" parameterType="com.star.vo.BookVO"> insert into t_book_vue(bookname,booktype,price) <trim prefix="values " suffixOverrides=","> <foreach collection="books" separator="," item="book"> (#{book.bookname},#{book.booktype},#{book.price}) </foreach> </trim> </insert> <!-- 实现批量删除 --> <delete id="deleteBookBatch" parameterType="com.star.vo.BookVO"> DELETE FROM t_book_vue WHERE id in <foreach collection="books" open="(" close=")" item="book" separator=","> #{book.id} </foreach> </delete>
更新
如果要更新多条记录为同样的数据,则可以用:
UPDATE t_book_vue SET bookname = 'course1',price=123.22 WHERE id in ('id1', 'id2', 'id3);
更新多条记录的多个字段为不同的值,是比较常用的场景,比较普通的写法就是循环更新sql,一次执行多条更新语句,那么mapper映射文件写法应该如下:
<update id="updateBookBatch" parameterType="java.util.List"> <foreach collection="list" item="item" separator=";"> update t_book_vue <set> bookname=#{item.bookname},price=#{item.price} </set> where id = ${item.id} </foreach> </update>
要注意的是,此种方式要想成功,必须在数据库连接url最后面带上一个允许执行多次的参数(例如: jdbc:mysql://localhost:3306/mysqlTest?characterEncoding=utf-8&allowMultiQueries=true):
&allowMultiQueries=true
另一种方式为sql的case when语法实现批量插入,最终只会产生一条sql,数据量过大可能引起巨大的开销(拼接sql过程复杂):
<!-- 实现批量更新(利用case when) --> <update id="updateBookBatch" parameterType="com.star.vo.BookVO"> update t_book_vue <trim prefix="set" suffixOverrides=","> <foreach collection="books" open="bookname = case" close="end," item="i"> <if test="i.id!=null and i.bookname!=null"> when id=#{i.id} then #{i.bookname} </if> </foreach> <foreach collection="books" open="price =case" close="end," item="i"> <if test="i.id!=null and i.price!=null"> when id=#{i.id} then #{i.price} </if> </foreach> <foreach collection="books" open="booktype =case" close="end," item="i"> <if test="i.id!=null and i.booktype!=booktype"> when id=#{i.id} then #{i.booktype} </if> </foreach> </trim> where <foreach collection="books" separator="or" item="i" index="index"> id=#{i.id} </foreach> </update>
最后一种Mysql独有的语法:duplicate key update效率是最高的,通过批量插入检查,如果已存在,则更新,所以可以变相达到批量修改的效果,但是一般大公司都禁用,公司一般都禁止使用REPLACE INTO和INSERT INTO … ON DUPLICATE KEY UPDATE,因为这种sql有可能会造成数据丢失和主从上表的自增id值不一致。
比如这句sql:
INSERT INTO t_book_vue(id,bookname,price,booktype)VALUES(67,'你好',123.23,'1-4'),(66,'不好',321.32,'1-6') ON DUPLICATE KEY UPDATE bookname=VALUES(bookname),price=VALUES(price),booktype = VALUES(booktype);
它的执行结果:
我们在插入的时候发现了已经存在的主键,所以它执行了覆盖操作,变相的达到了更新的目的所以影响行数为4(如果均未发现主键则是2),此表中必须有唯一索引或主键,否则会产生上述问题。
在mybatis中实现如下,参考完整源码移步:Mybatis案例
<insert id="updateBookBatch" parameterType="com.star.vo.BookVO"> INSERT INTO t_book_vue(id,bookname,price,booktype)VALUES <foreach collection="books" item="item" separator=","> (#{item.id},#{item.bookname},#{item.price},#{item.booktype}) </foreach> ON DUPLICATE KEY UPDATE bookname=VALUES(bookname),price=VALUES(price),booktype=VALUES(booktype) </insert>