最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

解析MyBatisPlus解決邏輯刪除與唯一索引的兼容問題

 更新時(shí)間:2023年04月14日 08:34:50   作者:雨點(diǎn)的名字  
這篇文章主要介紹了MyBatisPlus解決邏輯刪除與唯一索引的兼容問題,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

需求背景

比如有張用戶表,在插入或者更新數(shù)據(jù)的時(shí)候,我們需要 用戶名稱(username),不能重復(fù)。

我們首先考慮的是給該字段創(chuàng)建唯一索引

create unique index uni_username on user(username)

似乎這樣就可以了,然而事情并沒有那么簡(jiǎn)單。

因?yàn)槲覀儽碇械臄?shù)據(jù)在刪除的時(shí)候不會(huì)真的的刪除,而是采用邏輯刪除,會(huì)有一個(gè) deleted 字段使用0,1標(biāo)識(shí)未刪除與已刪除。

當(dāng)然我們可以考慮將 username + deleted 組合成一個(gè)聯(lián)合唯一索引。

create unique index uni_username_deleted on user(username,deleted)

這樣就ok了嗎?

其實(shí)會(huì)有一個(gè)新的問題,就是如果同一個(gè)用戶名如果被刪除一次。

再去刪除會(huì)發(fā)現(xiàn)系統(tǒng)報(bào)錯(cuò)了,因?yàn)樵摋l數(shù)據(jù)已經(jīng)存在了,不能在刪除了。

是不是很多時(shí)候因?yàn)檫壿媱h除與唯一索引的沖突,你就不創(chuàng)建唯一索引,想著自己寫的代碼自己有信心不會(huì)出現(xiàn)臟數(shù)據(jù)的。

這么想你就太天真啦,數(shù)據(jù)庫是我們最后一道防線,這道防線都不要了嘛?

阿里巴巴手冊(cè)有關(guān)索引規(guī)范,第一條就是

【強(qiáng)制】業(yè)務(wù)上具有唯一特性的字段,即使是組合字段,也必須建成唯一索引。

手冊(cè)還有這么一句話:

即使在應(yīng)用層做了非常完善的校驗(yàn)和控制,只要沒有唯一索引,根據(jù)墨菲定律,必然有臟數(shù)據(jù)產(chǎn)生。

所以唯一索引非常有必要?。?!

那該怎么做能讓邏輯刪除與唯一索引兼容?

現(xiàn)在大家比較通用的辦法就是

我們依舊可以將 username + deleted 組合成一個(gè)聯(lián)合唯一索引,但是刪除的時(shí)候deleted不再是固定的1,而是當(dāng)前的主鍵ID,也就是deleted不等于0都是刪除狀態(tài),如果刪除了那deleted值=id值

既然確立了解決方案,那就該思考怎么做?

二、MyBatisPlus邏輯刪除

MyBatisPlus是支持邏輯刪除的,如果確定在哪個(gè)字段是邏輯刪除字段,那就在該字段上添加一個(gè)注解

  /**
     * 1、刪除 0、未刪除
     */
    @TableLogic(value = "0", delval = "1")
    private Integer deleted;

這個(gè)一來操作數(shù)據(jù)是會(huì)自動(dòng)變成如下:

  • 查詢時(shí): 查詢條件會(huì)自動(dòng)加上 'AND deleted = 0'
  • 刪除時(shí): 自定添加 'UPDATE SET deleted = 1 … WHERE … AND deleted = 0'

如果你想刪除的時(shí)候不再是固定1而是id值,那么就可以這樣改

    @TableLogic(value = "0", delval = "id")
    private Integer deleted;

如果想改成全局的那么在配置文件中添加

mybatis-plus:
  global-config:
    db-config:
      logic-delete-value: 1 # 邏輯已刪除值(默認(rèn)為 1)
      logic-not-delete-value: 0 # 邏輯未刪除值(默認(rèn)為 0)

三、測(cè)試

1、用戶表

CREATE TABLE `user` (
  `id` int unsigned  AUTO_INCREMENT COMMENT '主鍵',
  `username` varchar(128)  COMMENT '用戶名',
  `phone` varchar(32)  COMMENT '手機(jī)號(hào)',
  `sex` char(1)  COMMENT '性別',
  `create_time` datetime  COMMENT '創(chuàng)建時(shí)間',
  `update_time` datetime  COMMENT '更新時(shí)間',
  `deleted` tinyint DEFAULT '0' COMMENT '1、刪除 0、未刪除',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 

2、創(chuàng)建對(duì)應(yīng)實(shí)體

@Data
@Accessors(chain = true)
@TableName("user")
public class UserDO implements Serializable {

    private static final long serialVersionUID = 1L;

    @TableId(type = IdType.AUTO)
    private Integer id;
    /**
     * 用戶名
     */
    private String username;
    /**
     * 手機(jī)號(hào)
     */
    private String phone;
    /**
     * 性別
     */
    private String sex;
    /**
     * 創(chuàng)建時(shí)間
     */
    private LocalDateTime createTime;
    /**
     * 更新時(shí)間
     */
    private LocalDateTime updateTime;

    /**
     * 1、刪除 0、未刪除
     */
    private Integer deleted;
}

3、物理刪除測(cè)試

注意: 目前 deleted 字段是沒有添加 @TableLogic注解,同是在全局也沒有定義邏輯刪除

我們來看下刪除示例

    @Test
    public void deleteById() {
        //方式一:根據(jù)id刪除
        mapper.deleteById(10);
        //方式二:根據(jù)指定字段刪除
        LambdaQueryWrapper<UserDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserDO::getSex, "男");
        mapper.delete(wrapper);
        //方式三:手動(dòng)邏輯刪除
        UserDO userDO = new UserDO();
        userDO.setId(10);
        userDO.setDeleted(1);
        mapper.updateById(userDO);
    }

執(zhí)行結(jié)果

--方式1
DELETE FROM user WHERE id=10
--方式2
DELETE FROM user WHERE (sex = '男')
--方式3
UPDATE user SET deleted=1 WHERE id=10

我們通過結(jié)果可以看出,如果不添加邏輯刪除標(biāo)識(shí) 那刪除就是物理刪除。

4、邏輯刪除測(cè)試

我們?cè)赿eleted屬性字段 添加 邏輯刪除標(biāo)識(shí)

 @TableLogic(value = "0", delval = "id")
 private Integer deleted;

我們?cè)賮韴?zhí)行上面三個(gè)刪除,看下執(zhí)行結(jié)果

--方式1
UPDATE user SET deleted=id WHERE id=10 AND deleted=0
--方式2
UPDATE user SET deleted=id WHERE deleted=0 AND (sex = '男')
--方式3
報(bào)錯(cuò)了

從執(zhí)行結(jié)果來看,方式一和方式二都從之前的物理刪除變成了邏輯刪除。

但為什么方式三會(huì)報(bào)錯(cuò)呢?我們來看下報(bào)錯(cuò)的結(jié)果

發(fā)現(xiàn)問題了,最終執(zhí)行的SQL竟然是:

UPDATE user  WHERE id=?  AND deleted=0

為什么是這樣,正常不應(yīng)該是

UPDATE user SET deleted=1  WHERE id=?  AND deleted=0

這個(gè)就需要去看Mybatisplus到底做了什么操作,改變了我們的SQL

真相大白了

Mybatisplus在updateById更新時(shí),如果已經(jīng)加了邏輯刪除標(biāo)記,那做SQL拼接的時(shí)候,會(huì)自動(dòng)過濾掉邏輯刪除的Set拼接

所以在實(shí)際開發(fā)中就非常注意,如果你的項(xiàng)目一開始是沒有加Mybatisplus邏輯刪除標(biāo)識(shí)的,后面你在加邏輯刪除標(biāo)識(shí)時(shí),不是說加了就好了。

你還需要考慮對(duì)整體項(xiàng)目有沒有影響,如果之前是用updateById做邏輯刪除,那就會(huì)導(dǎo)致之前的刪除失敗甚至是報(bào)錯(cuò),這一點(diǎn)一定要注意。

到此這篇關(guān)于MyBatisPlus解決邏輯刪除與唯一索引的兼容問題的文章就介紹到這了,更多相關(guān)MyBatisPlus邏輯刪除與唯一索引內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java中Logger定義的3種方式及最佳實(shí)踐

    Java中Logger定義的3種方式及最佳實(shí)踐

    這篇文章主要介紹了Java中三種常見的Logger定義方式及其優(yōu)缺點(diǎn),同時(shí)文章還討論了Logger的命名和訪問修飾符的最佳實(shí)踐,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2025-02-02
  • Java獲取XML節(jié)點(diǎn)總結(jié)之讀取XML文檔節(jié)點(diǎn)的方法

    Java獲取XML節(jié)點(diǎn)總結(jié)之讀取XML文檔節(jié)點(diǎn)的方法

    下面小編就為大家?guī)硪黄狫ava獲取XML節(jié)點(diǎn)總結(jié)之讀取XML文檔節(jié)點(diǎn)的方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2016-10-10
  • 利用Spring插件實(shí)現(xiàn)策略模式的案例詳解

    利用Spring插件實(shí)現(xiàn)策略模式的案例詳解

    Spring插件提供了一種更實(shí)用的插件開發(fā)方法,它提供了插件實(shí)現(xiàn)擴(kuò)展核心系統(tǒng)功能的核心靈活性,但當(dāng)然不提供核心OSGi功能,如動(dòng)態(tài)類加載或運(yùn)行時(shí)安裝和部署插件,本文就來聊下如何使用spring插件來實(shí)現(xiàn)策略模式,需要的朋友可以參考下
    2023-05-05
  • maven <repositories>標(biāo)簽和<pluginRepositories>標(biāo)簽的使用

    maven <repositories>標(biāo)簽和<pluginRepositories>標(biāo)簽的使用

    這篇文章主要介紹了maven <repositories>標(biāo)簽和<pluginRepositories>標(biāo)簽的使用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • 解決使用IDEA時(shí)跳轉(zhuǎn)到.class的問題

    解決使用IDEA時(shí)跳轉(zhuǎn)到.class的問題

    這篇文章主要介紹了解決使用IDEA時(shí)跳轉(zhuǎn)到.class的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • Java調(diào)用微信支付功能的方法示例代碼

    Java調(diào)用微信支付功能的方法示例代碼

    這篇文章主要介紹了Java調(diào)用微信支付功能的方法示例代碼,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-08-08
  • mybatisplus的坑?insert標(biāo)簽insert?into?select無參數(shù)問題的解決

    mybatisplus的坑?insert標(biāo)簽insert?into?select無參數(shù)問題的解決

    這篇文章主要介紹了mybatisplus的坑?insert標(biāo)簽insert?into?select無參數(shù)問題的解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • Java基礎(chǔ)學(xué)習(xí)之接口詳解

    Java基礎(chǔ)學(xué)習(xí)之接口詳解

    接口,是Java語言中一種引用類型,是方法的集合,如果說類的內(nèi)部封裝了成員變量、構(gòu)造方法和成員方法,那么接口的內(nèi)部主要就是封裝了方法。本文通過一些示例詳細(xì)為大家展示了接口的使用,需要的可以參考一下
    2022-10-10
  • Android 屏幕分辨率的整理

    Android 屏幕分辨率的整理

    這篇文章主要介紹了Android 屏幕分辨率的整理的相關(guān)資料,這里整理了常見的分辨率希望能幫助到大家,需要的朋友可以參考下
    2017-08-08
  • JSON序列化導(dǎo)致Long類型被搞成Integer的坑及解決

    JSON序列化導(dǎo)致Long類型被搞成Integer的坑及解決

    這篇文章主要介紹了JSON序列化導(dǎo)致Long類型被搞成Integer的坑及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-01-01

最新評(píng)論

海盐县| 绥江县| 桑日县| 柯坪县| 莲花县| 南陵县| 吴江市| 文山县| 兴和县| 五指山市| 霍州市| 开平市| 天峻县| 赤城县| 兖州市| 邢台市| 靖西县| 共和县| 金坛市| 庐江县| 光山县| 克拉玛依市| 新乡市| 乐至县| 普定县| 江口县| 莱芜市| 宾阳县| 万山特区| 嵊州市| 浦江县| 九台市| 观塘区| 平塘县| 长泰县| 黎城县| 甘孜| 依兰县| 交口县| 叶城县| 兴城市|