mybatisupdate语句,mybatis forupdate

  mybatisupdate语句,mybatis forupdate

  00-1010 Insertrupdate函数的实现需求Mybatis学习笔记的实现3360 Insertrupdate环境简介DaoMapper XML文件行别名主键和唯一索引

  

目录

 

  00-1010最近在项目开发中,我们遇到了这样一个需求:同一个数据(可能不一样)一天需要入库两次。如果数据不存在,它将被插入,如果存在,它将被更新。所以我用了Mybatis的InsertOrUpdate函数。

  00-1010每次对数据库进行操作之前,先根据id检查是否有记录,如果有则进行更新操作,如果没有则进行插入操作。

  模型类代码如下。Count是一个非业务字段(也不是表中的字段),但它只是Mybatis插入或更新的一个附加字段。

  进口龙目岛。数据;@Datapublic类Sheet {/** *主键*/私有字符串id;/* * *客户名称*/私有字符串customerName/** * 。省略其他字段*//* *此字段为非业务字段。Mybatis配置文件需要转到这个字段,方便insertOrUpdate操作*/private int count;}Mybatis的mapper.xml配置文件代码如下。

  代码含义:首先执行selectKey语句,将结果赋给Sheet类的count属性。

  如果计数大于0,则意味着记录已经存在,并且执行更新操作。如果计数等于0,则意味着没有记录,并且执行插入操作。update ID= insertOrUpdate parameter type= Sheet select key key property= count result type= int order= BEFORE select count(1)from Sheet where ID=# { ID }/select key if test= count 0 如果test=customerName!=null和customerName!= CUSTOMER _ NAME=# { customerName },/if /set其中ID=# { ID }/if if test= count==0 insert into sheet trim prefix=( suffix=) suffix overrides=, ID,if test=customerName!=null和customerName!= 客户名称,/if /trim trim前缀=值(后缀=)后缀覆盖=, #{id},if测试=客户名称!=null和customerName!= # { CustomerName } ,/if/trim/if/updateSelectKey标记可以设置更新标记中parameterType属性(模型类)对应的对象的属性值。selectKey标记的属性描述:

  Property:应该为其设置SELECT KEY语句结果的目标属性。这对应于Sheet类的count属性。结果类型

  code>:结果的类型,此处为属性count的类型。order:可以被设置为 BEFORE 或 AFTER。BEFORE表示先执行selectKey语句,后执行update语句;AFTER表示先执行update语句,后执行selectKey语句。

 

  

Mybatis学习笔记:InsertOrUpdate

 

  

环境

Intellij IDEA : 2021.3Mysql:8+java:1.8+

 

  

前言

以前使用mongodb、JOOQ组件的时候都是有insertOrUpdate的功能,现在使用mybatis似乎没有提供这种功能。

 

  最近研究了,这个功能其实是mysql提供的,利用的是duplicate key update;

  假设,我们有这么一张表:

  

CREATE TABLE `relation` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 主键, `name` varchar(64) NOT NULL DEFAULT COMMENT 名称, `relation_id` varchar(64) NOT NULL DEFAULT COMMENT 关联id, `type` int(11) NOT NULL DEFAULT 0 COMMENT 0:默认, `is_delete` tinyint(4) NOT NULL DEFAULT 0 COMMENT 状态值, `create_at` varchar(64) NOT NULL DEFAULT COMMENT 创建人, `created` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间, `update_at` varchar(64) NOT NULL DEFAULT COMMENT 更新人, `updated` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 更新人, PRIMARY KEY (`id`), UNIQUE KEY `ix_relation_id_type` (`relation_id`,`type`) USING BTREE) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

注意: ix_relation_id_type:唯一索引

 

  

 

  

Dao

@Mapperpublic interface FlowModelMapper {    void insertOrUpdate(List<FlowModel> flowModel);}

 

  

Mapper XML文件

<insert id="insertOrUpdate"> insert into flow_model(name, relation_id, type, is_delete,create_at,update_at) values <foreach collection="list" item="p" index="index" separator=","> ( #{p.name}, #{p.relationId}, #{p.type}, #{p.isDelete}, #{p.createAt}, #{p.updateAt} ) </foreach> on duplicate key update name=values(name), update_at=values(update_at)</insert>

说明:

 

  on duplicate key update这个是非常关键的地方,需要有唯一键和主键。on duplicate key update后面跟着的name=values(name)算是一个固定写法,作用:动态的传入要修改的值。在MySQL 8.0.20之后,VALUES()在mysql未来的版本会被删除。

  官方建议,使用列别名的方式来写:

  

<insert id="insertOrUpdate"> insert into flow_model(name, relation_id, type, is_delete,create_at,update_at) values <foreach collection="list" item="p" index="index" separator=","> ( #{p.name}, #{p.relationId}, #{p.type}, #{p.isDelete}, #{p.createAt}, #{p.updateAt} ) </foreach> AS fm on duplicate key update name=fm.name, update_at=fm.update_at</insert>

 

  

行别名

insert into …values

 

  语法:insert into ...values(...) AS 行别名 ON DUPLICATE KEY UPDATE 使用行别名。

  例如:下面的 new就是行别名。

  

INSERT INTO t1 (a,b,c) VALUES (1,2,3),(4,5,6) AS new  ON DUPLICATE KEY UPDATE c = new.a+new.b;

列别名

 

  或者是:insert into ...values(...) AS 行别名(列别名,列别名,列别名) ON DUPLICATE KEY UPDATE 使用别名

  下面的m,n,p是随便取的列别名

  

INSERT INTO t1 (a,b,c) VALUES (1,2,3),(4,5,6) AS new(m,n,p)  ON DUPLICATE KEY UPDATE c = m+n;

注意:

 

  当使用列别名时,必须在VALUES子句后面使用行别名,即使在后面的子句中不使用行别名。

  除了insert into … values 场景,insert into …set场景也适用。

  语法和上面是一样的:

  

INSERT INTO t1 SET a=1,b=2,c=3 AS new  ON DUPLICATE KEY UPDATE c = new.a+new.b;INSERT INTO t1 SET a=1,b=2,c=3 AS new(m,n,p)  ON DUPLICATE KEY UPDATE c = m+n;

 

  

主键和唯一索引

现在假设我们有这些索引:

 

  唯一索引:biz_id、name、code

  主键:id

  

insert into template_url(id,name, code, url, scope, description, biz_id, create_by, create_user_id, update_by, update_user_id) values (1,yutao,yutao,www.baidu.com,yutao,yutao,0,yutao,0,yutao,0 ) ON DUPLICATE KEY UPDATEname=values(name), description=values(description), url=values(url), scope=values(scope), update_by=values(update_by), update_user_id=values(update_user_id)

主键冲突

 

  假设这时,主键冲突,那么MySQL就会接着判断是否 唯一索引冲突:

  ① 唯一索引不冲突,那么久执行更新

  ② 唯一索引冲突,就会报错:

  

1062 - Duplicate entry '0-yutao-yutao111' for key 'template_url.uk_biz_id_code_name', Time: 0.004000s

 

  

编辑时,唯一索引的字段不要修改

 

  小结一下:insertOrUpdate的实现是基于mysql的on duplicate key update 来实现的。

  使用ON DUPLICATE KEY UPDATE,如果行作为新行插入,则每行受影响的行值为1。如果更新现有行,则每行受影响的行值为2;如果将现有行设置为其当前值,则每行受影响的行值为0(可以通过配置,使其受影响的行值为1)。

  官方地址:

  13.2.6.2 INSERT … ON DUPLICATE KEY UPDATE Statement

  以上为个人经验,希望能给大家一个参考,也希望大家多多支持盛行IT。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: