Mybatis学习笔记:实现insertOrUpdate

环境

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

前言

以前使用mongodbJOOQ组件的时候都是有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

@Mapper
public 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>

说明:

  1. on duplicate key update这个是非常关键的地方,需要有唯一键主键
  2. 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;

注意:

  1. 当使用列别名时,必须在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;

主键和唯一索引

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

  1. 唯一索引:biz_id、name、code
  2. 主键: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 UPDATE
	name=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

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

总结

  1. insertOrUpdate的实现是基于mysql的on duplicate key update 来实现的。
  2. 使用ON DUPLICATE KEY UPDATE,如果行作为新行插入,则每行受影响的行值为1。如果更新现有行,则每行受影响的行值为2;如果将现有行设置为其当前值,则每行受影响的行值为0(可以通过配置,使其受影响的行值为1)。

官方地址:
13.2.6.2 INSERT … ON DUPLICATE KEY UPDATE Statement

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: Mybatis-Plus中的insertOrUpdate是一种操作,它可以在数据库中执行插入或更新操作。如果数据库中已经存在相同的记录,则会执行更新操作,否则会执行插入操作。这种操作可以简化代码,减少重复的判断和操作,提高开发效率。同时,Mybatis-Plus还提供了其他方便的操作,如批量插入、批量更新等,可以满足不同的需求。 ### 回答2: MyBatis-Plus是一个开源的MyBatis增强工具包,提供了许多便捷的功能和API,其中包括insertOrUpdate方法。 insertOrUpdate方法是MyBatis-Plus中的一个常用方法,它可以根据主键判断数据是否存在,如果存在则更新数据,如果不存在则插入数据。 在使用insertOrUpdate方法时,我们需要先创建实体类,并且给实体类的主键属性打上@Id注解,示例如下: ``` @Data public class User { @Id private Long id; private String name; private Integer age; } ``` 接下来,在Mapper接口中定义insertOrUpdate方法: ``` int insertOrUpdate(User user); ``` 然后在Mapper.xml文件中实现insertOrUpdate方法,示例如下: ``` <insert id="insertOrUpdate" parameterType="com.example.demo.entity.User"> <!-- 判断数据是否存在 --> <if test="id != null"> select count(*) from user where id = #{id} </if> <!-- 根据数据是否存在执行不同的SQL语句 --> <choose> <!-- 数据存在则更新数据 --> <when test="_parameter.id != null and @com.baomidou.mybatisplus.core.toolkit.StringUtils@checkValNotNull(@java.lang.Long@valueOf(_parameter.id))"> update user set name = #{name}, age = #{age} where id = #{id} </when> <!-- 数据不存在则插入数据 --> <otherwise> insert into user(name, age) values(#{name}, #{age}) </otherwise> </choose> </insert> ``` 最后,在Java代码中调用insertOrUpdate方法即可: ``` @Autowired private UserMapper userMapper; User user = new User(); user.setId(1L); user.setName("Tom"); user.setAge(20); userMapper.insertOrUpdate(user); ``` 以上就是MyBatis-Plus中insertOrUpdate方法的用法。通过使用该方法,可以方便地实现数据的插入和更新,提高开发效率。 ### 回答3: Mybatis-Plus 中的 insertOrUpdate 方法可以在执行插入操作时,判断插入的数据是否存在,若存在则执行更新操作。这种操作方式可以帮助开发者在插入或更新数据时省去一次查询的步骤,提升程序的执行效率。 使用 insertOrUpdate 方法需要注意以下几点: 1. 需要在对应的实体类中设置好主键生成策略,以便判断数据是否存在。 2. 在调用 insertOrUpdate 方法时,传入需要插入或更新的实体对象即可。 3. 若插入的数据已经存在,则其中的值会被更新为传入对象中的值。 对于像 Mybatis-Plus 这样的ORM框架,优化常见的方式就是减少不必要的SQL查询。而这种插入或更新操作方式正是实现这个优化目标的一种方式。相比于先查询再根据查询结果进行插入或更新,insertOrUpdate 方法可以减少了一次查询的步骤,从而提升了程序的执行效率。 总之,mybatis-plus 中的 insertOrUpdate 方法可以帮助开发者在插入或更新数据时省去一次查询的步骤,提升程序的执行效率。对于需要进行插入或更新操作的场景,建议使用该方法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

山鬼谣me

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值