數據庫幻讀解決方案

有時候我們會有業務場景去解決數據庫幻讀現象:(比如某條記錄的某幾個屬性合起來需要在記錄裏唯一) 

這個時候我們需要做的是添加一個校驗字段對他做唯一約束,值是這幾個字段的拼接

這裏爲什麼用校驗字段而不用原字段呢? (有時候我們在做刪除的時候只做邏輯刪除 這時候唯一約束就好導致失效的記錄讓有效的記錄無法插入, 而校驗字段不一樣 你在做失效處理的時候給校驗字段賦一個隨機值就好了)

一般要解決幻讀的場景我們都需要(不存在插入並且返回插入值 存在直接查詢結果值)

以下是代碼示例

 public ComArea findAreaOrAdd(String comCode, String name, String flag, boolean throwException) {
        if (name == null || name.equals("null")) {
            logger.error("插入失敗 請檢查name是否位空 areaId={}", name);
            throw new BaseRuntimeException("0x00110301", "更新失敗 請檢查name是否位空");
        }
        ComArea comArea = new ComArea();
        comArea.setComcode(comCode);
        comArea.setComAreaId(UUID.randomUUID().toString().replace("-", ""));
        comArea.setName(name);
        String comFlag = "1" + flag.substring(1, flag.length());
        comArea.setComFlag(comFlag);
        comArea.setFlag(flag);
        comArea.setValid("Y");
        comArea.setDateCreate(new Date());
        comArea.setDateModify(new Date());
        //因爲幻讀會導致生成重複的code code=>comcode+name md5生成的
        String code = DigestUtils.md5DigestAsHex((comCode + name).getBytes());
        comArea.setCode((comCode + code).substring(0, 32));
        //standardcode 做了唯一約束刪除的時候要給standardcode一個隨機值
        comArea.setStandardCode(comArea.getCode());
        ComArea comArea1 = null;
        try {
            comArea1 = comAreaService.save(comArea) ? comArea : null;
        } catch (Exception e) {
            if (throwException) {

                throw new BaseRuntimeException("0x00110301", "插入失敗 請檢查名稱是否重複 [" + name + "]");

            } else {
                comArea1 = comAreaService.getOne(new QueryWrapper<ComArea>().lambda().eq(ComArea::getComcode, comCode)
                                .eq(ComArea::getName, name).eq(ComArea::getValid, "Y")
                        , false);
            }
        }
        return comArea1;
    }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章