详解MyBatisPlus逻辑删除与唯一索引冲突问题

1、问题背景:

在开发中,我们经常会有逻辑删除和唯一索引同时使用的情况。但当使用mybatis plus时,如果同时使用逻辑删除和唯一索引,会报数据重复Duplicate entry的问题。

举个例子:

原来数据库结构:

这里location_id是唯一索引

CREATE TABLE `eam_location` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `location_id` varchar(50) UNIQUE NOT NULL COMMENT '位置代码',
  `location_level` tinyint(1) NOT NULL COMMENT '位置级别',
  `location_name` varchar(50) NOT NULL COMMENT '位置名称',
  `parent_location_id` varchar(50) COMMENT '上级位置代码',
  `delete_flag` tinyint(1) DEFAULT 0 COMMENT '软删除',
  `version` int(11) DEFAULT 1 COMMENT '乐观锁',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

这里在删除添加某一条数据后,delete_flag变成0,当删除后delete_flag会变成1,再次添加相同的数据时,由于数据库检测不到原来数据,会报数据重复Duplicate entry的问题

解决办法:参考逻辑删除与唯一约束的需求冲突

SQL数据结构,将delete_flag用时间戳进行表示,唯一索引变成了联合唯一索引 UNIQUE KEY unique_location_delete_flag(location_id, delete_flag) ,当添加一条数据时,delete_flag变成null,当删除数据时,delete_flag变成删除时的一个时间戳。再次添加相同数据时,由于添加的数据是联合唯一索引unique_location_delete_flag ,delete_flag为null,不会产生冲突,多次删除也是,完美解决问题。

CREATE TABLE `eam_location` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `location_id` varchar(50) NOT NULL COMMENT '位置代码',
  `location_level` tinyint(1) NOT NULL COMMENT '位置级别',
  `location_name` varchar(50) NOT NULL COMMENT '位置名称',
  `parent_location_id` varchar(50) COMMENT '上级位置代码',
  `delete_flag` datetime COMMENT '软删除',
  `version` int(11) DEFAULT 1 COMMENT '乐观锁',
  PRIMARY KEY (`id`),
  UNIQUE KEY `unique_location_delete_flag`(`location_id`, `delete_flag`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

entity类:

@AllArgsConstructor
@NoArgsConstructor
@Builder(toBuilder = true)
@Data
@EqualsAndHashCode(callSuper = false)
public class EamEquipmentType implements Serializable {

  private static final long serialVersionUID = 1L;

  /**
   * 数据库自增id
   */
  @TableId(value = "id", type = IdType.AUTO)
  private Integer id;

  /**
   * 设备类型编号
   */
  private String typeId;

  /**
   * 设备类型
   */
  private String typeName;

  /**
   * 设备厂商
   */
  private String manufacture;

  /**
   * 设备型号
   */
  private String model;

  /**
   * 标准设备bom 0:未创建 1:已创建
   */
  private Boolean typeBom;

  /**
   * 标准设备bom id
   */
  private Integer typeBomId;

  /**
   * 创建时间
   */
  private LocalDateTime createTime;

  /**
   * 软删除
   */
  @TableLogic()
  @TableField(fill = FieldFill.INSERT)
  private LocalDateTime deleteFlag;

  /**
   * 乐观锁
   */
  @Version
  @TableField(fill = FieldFill.INSERT)
  private Integer version;

yml配置文件:

mybatis-plus:
 global-config:
  db-config:
   logic-delete-value: "now()" #逻辑删除值是个db获取时间的函数
   logic-not-delete-value: "null" #逻辑未删除值为字符串 "null"

到此这篇关于详解MyBatisPlus逻辑删除与唯一索引冲突问题的文章就介绍到这了,更多相关MyBatisPlus逻辑删除与唯一索引冲突内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • MybatisPlus实现逻辑删除功能

    逻辑删除 你有没有见过某些网站进行一些删除操作之后,你看不到记录了但是管理员却能够查看到.这里就运用到了逻辑删除. 什么是逻辑删除? 逻辑删除的本质是修改操作,所谓的逻辑删除其实并不是真正的删除,而是在表中将对应的是否删除标识(deleted)或者说是状态字段(status)做修改操作.比如0是未删除,1是删除.在逻辑上数据是被删除的,但数据本身依然存在库中. 对应的SQL语句: update user set deleted=1 where id =1 and deleted=0 update

  • MybatisPlus中的删除和逻辑删除及区别介绍

    删除又分为逻辑删除和物理删除,那么它们有什么区别呢? 物理删除:真实删除,将对应数据从数据库中删除,之后查询不到此条被删除数据. 逻辑删除:假删除,将对应数据中代表是否被删除字段状态修改为"被删除状态",之后在数据库中仍旧能看到此条数据记录. 在我们日常开发中,为了保留数据,经常会使用逻辑删除的方式进行数据删除,下面我们就来看看物理删除与逻辑删除怎么实现的吧 首先假设我有这样一张表 实体类: package com.atguigu.mybatis_plus.entity; import

  • 详解MyBatisPlus逻辑删除与唯一索引冲突问题

    1.问题背景: 在开发中,我们经常会有逻辑删除和唯一索引同时使用的情况.但当使用mybatis plus时,如果同时使用逻辑删除和唯一索引,会报数据重复Duplicate entry的问题. 举个例子: 原来数据库结构: 这里location_id是唯一索引 CREATE TABLE `eam_location` ( `id` int(11) NOT NULL AUTO_INCREMENT, `location_id` varchar(50) UNIQUE NOT NULL COMMENT '位

  • MyBatis-Plus解决逻辑删除与唯一索引的问题

    目录 简介 问题复现 建库建表 代码 测试 解决方案 方案1:将字段设置为id(推荐) 方案2:将字段设置为当前时间(不推荐) 简介 说明 本文用示例介绍MyBatis-Plus如何解决逻辑删除与唯一索引的问题. 物理删除与逻辑删除 数据是很重要的,数据库里的数据在删除时一般不会用DELETE语句直接物理删除. 通常的做法是使用逻辑删除,也就是:新加一个标记是否删除的字段,在删除时不是真的删除,而是使用UPDATE语句将某个字段设置为删除状态.例如:"deleted_flag",0表示

  • 详解Mybatis-plus(MP)中CRUD操作保姆级笔记

    目录 一.什么是mybatis-plus 1.在java中访问数据库 2.Mybatis-plus简介 3.Mybatis-plus特性 二.第一个mybatis-plus开发 1.使用MP的步骤: 前提:数据库/表创建 2.mybatis-plus日志 三.MP操作CRUD 的 基本用法 1.添加数据后,获取主键值(MP可以自动实现主键回填) 2.更新数据 3.删除数据 4.查询数据 5.mybatis-plus中CRUD的底层实现原理 一.什么是mybatis-plus 1.在java中访问

  • 一文详解Mybatis-plus的介绍与使用

    目录 Mybatis-Plus简介 Mybatis-Plus特性 Mybatis-Plus实操 数据库相关配置 小项目运行配置 添加数据 删除数据 修改数据 查询数据 小结 Mybatis-Plus简介 Mybatis-Plus 是 MyBatis 的一个增强工具,专门针对于传统MyBatis开发中sql需要手动进行映射配置繁琐缺点的一款框架技术,这款框架技术提供了十分丰富的api供开发者们使用,在 MyBatis 的基础上只做增强不做改变,为简化开发.提高效率而生.MyBatis-Plus 已

  • 详解mybatis-plus使用@EnumValue注解的方式对枚举类型的处理

    前言: 在开发中,我们经常会用到诸如:性别(男/女).审核状态(未审核/审核中/已审核)之类的数据,通常会在数据库中使用一个数字类型的字段来标识,比如:性别,用1来表示男,2来表示女,而在代码中一般会定义成enum类型或静态常量来避免在业务代码中出现"0/1"这种魔法值,但是在数据库存储及前后端交互的时候,就需要进行转化:无论是在SQL.前端还是后台转化,都需要写相应的代码,无形中增加了开发工作量:mybatis-plus实现了对该问题的处理,能够让我们在查询数据库时,直接能够返回字段

  • 详解MyBatis-Plus Wrapper条件构造器查询大全

    一.引言 那么那么那么今天来说下MP中强大的条件查询功能. 本章是基于上个案例来讲的:MyBaits-Plus 快速入门案例 二.具体操作 首先来说说基本的查询吧,根据主键或者简单的查询条件进行查询. /** * 通过单个ID主键进行查询 */ @Test public void selectById() { User user = userMapper.selectById(1094592041087729666L); System.out.println(user); } /** * 通过多

  • 详解mybatis-plus的 mapper.xml 路径配置的坑

    mybatis-plus今天遇到一个问题,就是mybatis 没有读取到mapper.xml 文件. 特此记录一下,问题如下: org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.husy.mapper.SystemUserMapper.findUserByName at com.baomidou.mybatisplus.core.override.MybatisMapperMe

  • 详解MyBatis-Plus updateById方法更新不了空字符串/null解决方法

    最近遇到了Mybatis-Plus updateById(),更新某一个字段为null,却发现没有更新成功,发现有一个博客记录挺好的.转载过来,方便自己看. 一.简介 因为最近在忙项目,好久都没有更新博客,最近在项目中刚好遇到一个问题,就是在使用MyBatis-Plus updateById(xxx)的时候,居然更新不了字符串或者null,本文分享两种解决方案,具体大家可以根据自己的需求选择一种方法解决. 二.原理 在实际项目中,难免更新的时候,有可能会把已有的值更新成空字符串或者null,但是

  • 详解Mybatis-plus中更新date类型数据遇到的坑

    最近一年的项目都是在使用Mybatis-plus,感觉挺好用的,也没遇到很多问题,但是在最近项目上线之后,遇到了一些新的需要,在进行新版本开发的时候就开始遇到坑了,今天来说一下更新数据中有date类型数据的时候会出现的问题. 实体类部分字段如下: @Data @Builder @NoArgsConstructor @AllArgsConstructor public class ProductPo implements Serializable { /** * 产品主键,自增 */ privat

  • 详解mybatis-plus配置找不到Mapper接口路径的坑

    mybatis-plus今天遇到一个问题,就是mybatis 没有读取到mapper.xml 文件. 特此记录一下,问题如下: at com.baomidou.mybatisplus.core.override.MybatisMapperMethod$SqlCommand.<init>(MybatisMapperMethod.java:242) at com.baomidou.mybatisplus.core.override.MybatisMapperMethod.<init>(

随机推荐