Mybatis 批量更新实体对象方式
程序员文章站
2022-12-02 18:08:48
目录mybatis批量更新实体对象(1)dao层接口(2)mapper.xml 文件mybatis批量更新数据三种方法效率对比探讨批量更新数据三种写法的效率问题mybatis批量更新实体对象(1)da...
mybatis批量更新实体对象
(1)dao层接口
/** * 根据更新采购计划(批量) * @param plans */ void batchupdateplan(list<pubpurchaseplan> plans);
(2)mapper.xml 文件
<sql id="batchupdateplancondition"> <where> <foreach collection="list" item="item" open="( " separator=") or (" close=" )"> comid = #{item.comid} and id = #{item.id} </foreach> </where> </sql> <update id="batchupdateplan" parametertype="list"> update pub_purchase_plan <trim prefix="set" suffixoverrides=","> <trim prefix="warehouseid=case" suffix="end,"> <foreach collection="list" item="item" index="index"> when comid = #{item.comid} and id = #{item.id} then #{item.warehouseid} </foreach> </trim> <trim prefix="productid=case" suffix="end,"> <foreach collection="list" item="item" index="index"> when comid = #{item.comid} and id = #{item.id} then #{item.productid} </foreach> </trim> <trim prefix="amount=case" suffix="end,"> <foreach collection="list" item="item" index="index"> when comid = #{item.comid} and id = #{item.id} then #{item.amount} </foreach> </trim> <trim prefix="deleted=case" suffix="end,"> <foreach collection="list" item="item" index="index"> when comid = #{item.comid} and id = #{item.id} then #{item.deleted} </foreach> </trim> <trim prefix="price=case" suffix="end,"> <foreach collection="list" item="item" index="index"> when comid = #{item.comid} and id = #{item.id} then #{item.price} </foreach> </trim> <trim prefix="type=case" suffix="end,"> <foreach collection="list" item="item" index="index"> when comid = #{item.comid} and id = #{item.id} then #{item.type} </foreach> </trim> </trim> <include refid="batchupdateplancondition"/> </update>
mybatis批量更新数据三种方法效率对比
探讨批量更新数据三种写法的效率问题
实现方式有三种
- 1、用for循环通过循环传过来的参数集合,循环出n条sql
- 2、用mysql的case when 条件判断变相的进行批量更新
- 3、用on duplicate key update进行批量更新
下面进行实现。
注意第一种方法要想成功,需要在db链接url后面带一个参数 &allowmultiqueries=true
即: jdbc:mysql://localhost:3306/mysqltest?characterencoding=utf-8&allowmultiqueries=true
其实这种东西写过来写过去就是差不多一样的代码,不做重复的赘述,直接上代码。
<!-- 批量更新第一种方法,通过接收传进来的参数list进行循环着组装sql --> <update id="updatebatch" parametertype="java.util.list" > <foreach collection="list" item="item" index="index" open="" close="" separator=";"> update standard_relation <set > <if test="item.standardfromuuid != null" > standard_from_uuid = #{item.standardfromuuid,jdbctype=varchar}, </if> <if test="item.standardtouuid != null" > standard_to_uuid = #{item.standardtouuid,jdbctype=varchar}, </if> <if test="item.gmtmodified != null" > gmt_modified = #{item.gmtmodified,jdbctype=timestamp}, </if> </set> where id = #{item.id,jdbctype=bigint} </foreach> </update> <!-- 批量更新第二种方法,通过 case when语句变相的进行批量更新 --> <update id="updatebatch" parametertype="java.util.list" > update standard_relation <trim prefix="set" suffixoverrides=","> <trim prefix="standard_from_uuid =case" suffix="end,"> <foreach collection="list" item="i" index="index"> <if test="i.standardfromuuid!=null"> when id=#{i.id} then #{i.standardfromuuid} </if> </foreach> </trim> <trim prefix="standard_to_uuid =case" suffix="end,"> <foreach collection="list" item="i" index="index"> <if test="i.standardtouuid!=null"> when id=#{i.id} then #{i.standardtouuid} </if> </foreach> </trim> <trim prefix="gmt_modified =case" suffix="end,"> <foreach collection="list" item="i" index="index"> <if test="i.gmtmodified!=null"> when id=#{i.id} then #{i.gmtmodified} </if> </foreach> </trim> </trim> where <foreach collection="list" separator="or" item="i" index="index" > id=#{i.id} </foreach> </update> 批量更新第三种方法,用on duplicate key update <insert id="updatebatch" parametertype="java.util.list"> insert into standard_relation(id,relation_type, standard_from_uuid, standard_to_uuid, relation_score, stat, last_process_id, is_deleted, gmt_created, gmt_modified,relation_desc)values <foreach collection="list" item="item" index="index" separator=","> (#{item.id,jdbctype=bigint},#{item.relationtype,jdbctype=varchar}, #{item.standardfromuuid,jdbctype=varchar}, #{item.standardtouuid,jdbctype=varchar}, #{item.relationscore,jdbctype=decimal}, #{item.stat,jdbctype=tinyint}, #{item.lastprocessid,jdbctype=bigint}, #{item.isdeleted,jdbctype=tinyint}, #{item.gmtcreated,jdbctype=timestamp}, #{item.gmtmodified,jdbctype=timestamp},#{item.relationdesc,jdbctype=varchar}) </foreach> on duplicate key update id=values(id),relation_type = values(relation_type),standard_from_uuid = values(standard_from_uuid),standard_to_uuid = values(standard_to_uuid), relation_score = values(relation_score),stat = values(stat),last_process_id = values(last_process_id), is_deleted = values(is_deleted),gmt_created = values(gmt_created), gmt_modified = values(gmt_modified),relation_desc = values(relation_desc) </insert>
@override public void updatestandardrelations() { list<standardrelation> list=standardrelationmapper.selectbystandarduuid("xiemingjieupdate"); for(standardrelation tmp:list){ tmp.setstandardfromuuid(tmp.getstandardfromuuid()+"update"); tmp.setstandardtouuid(tmp.getstandardtouuid()+"update"); } long begin=system.currenttimemillis(); standardrelationmanager.updatebatch(list); long end=system.currenttimemillis(); system.out.print("当前的批量更新的方法用时"+(end-begin)+"ms"); }
sql语句for循环效率其实相当高的,因为它仅仅有一个循环体,只不过最后update语句比较多,量大了就有可能造成sql阻塞。
case when虽然最后只会有一条更新语句,但是xml中的循环体有点多,每一个case when 都要循环一遍list集合,所以大批量拼sql的时候会比较慢,所以效率问题严重。使用的时候建议分批插入。
duplicate key update可以看出来是最快的,但是一般大公司都禁用,公司一般都禁止使用replace into和insert into … on duplicate key update,这种sql有可能会造成数据丢失和主从上表的自增id值不一致。而且用这个更新时,记得一定要加上id,而且values()括号里面放的是数据库字段,不是java对象的属性字段。
根据效率,安全方面综合考虑,选择适合的很重要。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持。