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>
posted @ 2020-11-08 12:15  _未来可期  阅读(399)  评论(0编辑  收藏  举报