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

在SpringBoot+MyBatis中優(yōu)雅處理多表數(shù)據(jù)清洗的實(shí)現(xiàn)步驟

 更新時(shí)間:2025年03月06日 11:31:13   作者:好奇的菜鳥  
數(shù)據(jù)清洗是指對數(shù)據(jù)進(jìn)行處理和糾錯(cuò),以去除或修復(fù)數(shù)據(jù)集中存在的錯(cuò)誤、不致、不完整和冗余的數(shù)據(jù),從而使數(shù)據(jù)更加準(zhǔn)確、可靠和有用,本文給大家介紹了在SpringBoot和MyBatis中優(yōu)雅處理多表數(shù)據(jù)清洗的實(shí)現(xiàn)步驟,需要的朋友可以參考下

問題背景

在實(shí)際業(yè)務(wù)中,我們常會遇到數(shù)據(jù)冗余問題。例如,一個(gè)公司表(sys_company)中存在多條相同公司名的記錄,但只有一條有效(del_flag=0),其余需要?jiǎng)h除。刪除前需將關(guān)聯(lián)表(如合同草稿表、發(fā)票表等)的外鍵字段(如purchaser_id)替換為保留記錄的ID。這類問題通常涉及多表、多字段的動(dòng)態(tài)更新,如何高效且安全地實(shí)現(xiàn)?

解決方案

我們將通過以下步驟實(shí)現(xiàn):

  1. 配置化驅(qū)動(dòng):用配置類聲明需要處理的表和字段,避免硬編碼。
  2. 動(dòng)態(tài)SQL更新:通過MyBatis XML實(shí)現(xiàn)批量更新和刪除。
  3. 事務(wù)一致性:確保所有操作原子化執(zhí)行。

實(shí)現(xiàn)步驟

1. 定義實(shí)體類

CompanyRetainedInfo:封裝需保留的公司信息

import lombok.Data;

@Data
public class CompanyRetainedInfo {
    private String companyName;   // 公司名稱
    private Long retainedId;      // 需保留的公司ID(del_flag=0的記錄)
    private String retainedName;  // 需保留的公司名稱(與companyName一致)
}

• 作用:映射查詢結(jié)果,傳遞保留記錄的ID和名稱。
• Lombok@Data 自動(dòng)生成Getter/Setter和toString()方法。

2. 定義配置類

TableConfig:聲明需處理的表和外鍵關(guān)系

public class TableConfig {
    private String tableName;    // 表名(如contract_draft)
    private String idColumn;     // 外鍵ID字段(如purchaser_id)
    private String nameColumn;  // 名稱字段(如purchaser_name,可能為null)

    // 構(gòu)造器 + Getter/Setter
    public TableConfig(String tableName, String idColumn, String nameColumn) {
        this.tableName = tableName;
        this.idColumn = idColumn;
        this.nameColumn = nameColumn;
    }
}

3. 編寫MyBatis Mapper接口

CompanyCleanMapper:定義數(shù)據(jù)操作接口(無注解,純XML映射

@Mapper
public interface CompanyCleanMapper {
    // 查詢需保留的公司信息(del_flag=0)
    List<CompanyRetainedInfo> selectRetainedCompanies();

    // 根據(jù)公司名查詢待刪除的ID列表(del_flag!=0)
    List<Long> selectIdsToDelete(String companyName);

    // 更新關(guān)聯(lián)表的外鍵引用
    void updateForeignKeys(
        @Param("config") TableConfig config,
        @Param("retainedId") Long retainedId,
        @Param("retainedName") String retainedName,
        @Param("ids") List<Long> ids
    );

    // 刪除冗余公司記錄
    void deleteCompanies(@Param("ids") List<Long> ids);
}

4. 實(shí)現(xiàn)XML映射文件

CompanyCleanMapper.xml:定義動(dòng)態(tài)SQL邏輯

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mapper.CompanyCleanMapper">

    <!-- 查詢需保留的公司 -->
    <select id="selectRetainedCompanies" resultType="CompanyRetainedInfo">
        SELECT 
            company_name AS companyName, 
            id AS retainedId, 
            company_name AS retainedName
        FROM sys_company
        WHERE del_flag = 0
          AND company_name IN (
            SELECT company_name
            FROM sys_company
            GROUP BY company_name
            HAVING COUNT(*) > 1 AND SUM(del_flag = 0) = 1
          )
    </select>

    <!-- 查詢待刪除的ID列表 -->
    <select id="selectIdsToDelete" resultType="long">
        SELECT id
        FROM sys_company
        WHERE company_name = #{companyName}
          AND del_flag != 0
    </select>

    <!-- 動(dòng)態(tài)更新外鍵引用 -->
    <update id="updateForeignKeys">
        UPDATE ${config.tableName}
        SET
            <choose>
                <when test="config.nameColumn != null">
                    <!-- 同時(shí)更新ID和名稱字段 -->
                    ${config.idColumn} = #{retainedId},
                    ${config.nameColumn} = #{retainedName}
                </when>
                <otherwise>
                    <!-- 僅更新ID字段 -->
                    ${config.idColumn} = #{retainedId}
                </otherwise>
            </choose>
        WHERE
            ${config.idColumn} IN
            <foreach item="id" collection="ids" open="(" separator="," close=")">
                #{id}
            </foreach>
    </update>

    <!-- 批量刪除公司記錄 -->
    <delete id="deleteCompanies">
        DELETE FROM sys_company
        WHERE id IN
        <foreach item="id" collection="ids" open="(" separator="," close=")">
            #{id}
        </foreach>
    </delete>

</mapper>

5. 服務(wù)層實(shí)現(xiàn)

CompanyCleanService:配置化驅(qū)動(dòng)批量處理

@Service
@RequiredArgsConstructor
public class CompanyCleanService {
    private final CompanyCleanMapper companyCleanMapper;

    // 配置需要處理的表和字段
    private static final List<TableConfig> TABLE_CONFIGS = Arrays.asList(
        new TableConfig("contract_draft", "purchaser_id", "purchaser_name"),
        new TableConfig("invoice", "company_id", "company_name")
        // 按需添加其他表...
    );

    @Transactional
    public void cleanDuplicateCompanies() {
        // 1. 查詢所有需保留的公司
        List<CompanyRetainedInfo> retainedCompanies = companyCleanMapper.selectRetainedCompanies();
        
        for (CompanyRetainedInfo info : retainedCompanies) {
            // 2. 查詢待刪除的ID列表
            List<Long> idsToDelete = companyCleanMapper.selectIdsToDelete(info.getCompanyName());
            
            if (!idsToDelete.isEmpty()) {
                // 3. 更新所有關(guān)聯(lián)表的外鍵引用
                TABLE_CONFIGS.forEach(config -> 
                    companyCleanMapper.updateForeignKeys(
                        config, 
                        info.getRetainedId(), 
                        info.getRetainedName(), 
                        idsToDelete
                    )
                );
                
                // 4. 刪除冗余公司記錄
                companyCleanMapper.deleteCompanies(idsToDelete);
            }
        }
    }
}

關(guān)鍵設(shè)計(jì)說明

  1. 實(shí)體類與數(shù)據(jù)映射
    • CompanyRetainedInfo 通過別名(AS retainedId)直接映射查詢結(jié)果,避免額外轉(zhuǎn)換。
    • companyName 和 retainedName 字段值相同,但保留后者以明確語義。

  2. XML動(dòng)態(tài)SQL優(yōu)勢
    • <choose>:根據(jù)配置動(dòng)態(tài)決定是否更新名稱字段。
    • <foreach>:自動(dòng)展開ID列表為IN (id1, id2...),支持批量操作。
    • ${}占位符:安全引用配置的表名和字段名(非用戶輸入,無注入風(fēng)險(xiǎn))。

  3. 事務(wù)與性能優(yōu)化
    • @Transactional:保證“更新外鍵”和“刪除公司”操作的原子性。
    • 索引建議:對sys_company.company_name和關(guān)聯(lián)表的外鍵字段添加索引。

總結(jié)

通過 實(shí)體類封裝、配置化表關(guān)系 和 MyBatis動(dòng)態(tài)SQL,我們實(shí)現(xiàn)了一套可擴(kuò)展的多表數(shù)據(jù)清洗方案。這種模式的核心在于:

  1. 抽象變化部分:將表和字段的差異收斂到配置類中。
  2. 復(fù)用不變邏輯:批量更新和刪除操作由統(tǒng)一服務(wù)驅(qū)動(dòng)。
  3. 最小化侵入性:新增表只需修改配置,無需改動(dòng)核心邏輯。

該方案適用于用戶中心、商品系統(tǒng)等存在外鍵關(guān)聯(lián)的冗余數(shù)據(jù)處理場景,讀者可結(jié)合實(shí)際需求調(diào)整配置和SQL邏輯。

以上就是在SpringBoot+MyBatis中優(yōu)雅處理多表數(shù)據(jù)清洗的實(shí)現(xiàn)步驟的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot MyBatis多表數(shù)據(jù)清洗的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Java創(chuàng)建型模式之建造者模式詳解

    Java創(chuàng)建型模式之建造者模式詳解

    建造者模式,是一種對象構(gòu)建模式 它可以將復(fù)雜對象的建造過程抽象出來,使這個(gè)抽象過程的不同實(shí)現(xiàn)方法可以構(gòu)造出不同表現(xiàn)的對象。本文將通過示例講解建造者模式,需要的可以參考一下
    2023-02-02
  • Java如何實(shí)現(xiàn)對稱加密

    Java如何實(shí)現(xiàn)對稱加密

    這篇文章主要介紹了Java如何實(shí)現(xiàn)對稱加密問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • 如何利用Jackson序列化忽略指定類型的屬性詳解

    如何利用Jackson序列化忽略指定類型的屬性詳解

    這篇文章主要給大家介紹了關(guān)于如何利用Jackson序列化忽略指定類型的屬性,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-11-11
  • jar包運(yùn)行后顯示沒有主清單屬性的問題及解決

    jar包運(yùn)行后顯示沒有主清單屬性的問題及解決

    這篇文章主要介紹了jar包運(yùn)行后顯示沒有主清單屬性的問題及解決方案,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • 創(chuàng)建Jersey REST 服務(wù),基于Maven的實(shí)現(xiàn)

    創(chuàng)建Jersey REST 服務(wù),基于Maven的實(shí)現(xiàn)

    下面小編就為大家?guī)硪黄獎(jiǎng)?chuàng)建Jersey REST 服務(wù),基于Maven的實(shí)現(xiàn)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-06-06
  • Java串口通信JSerialComm的實(shí)現(xiàn)

    Java串口通信JSerialComm的實(shí)現(xiàn)

    本文介紹了使用JSerialComm庫進(jìn)行Java串口通信,包括引入庫的方式、設(shè)置和操作串口、發(fā)送與接收數(shù)據(jù)以及添加數(shù)據(jù)監(jiān)聽器,具有一定的參考價(jià)值,感興趣的可以了解一下
    2026-01-01
  • Jenkins安裝多個(gè)jdk版本并在項(xiàng)目中選擇對應(yīng)jdk版本

    Jenkins安裝多個(gè)jdk版本并在項(xiàng)目中選擇對應(yīng)jdk版本

    在使用jenkins構(gòu)建項(xiàng)目時(shí)會遇到不同的job需要配置不同版本的jdk,下面這篇文章主要給大家介紹了關(guān)于Jenkins安裝多個(gè)jdk版本并在項(xiàng)目中選擇對應(yīng)jdk版本的相關(guān)資料,需要的朋友可以參考下
    2024-03-03
  • Java?Map集合五種遍歷方式詳解與性能對比

    Java?Map集合五種遍歷方式詳解與性能對比

    Java中的Map集合是用于存儲鍵值對的接口,核心特點(diǎn)是鍵的唯一性,這篇文章主要介紹了Java?Map集合五種遍歷方式詳解與性能對比的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2026-01-01
  • 這一次搞懂Spring自定義標(biāo)簽以及注解解析原理說明

    這一次搞懂Spring自定義標(biāo)簽以及注解解析原理說明

    這篇文章主要介紹了這一次搞懂Spring自定義標(biāo)簽以及注解解析原理說明,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-08-08
  • Idea 2020.2 創(chuàng)建web、Spring項(xiàng)目的教程圖解

    Idea 2020.2 創(chuàng)建web、Spring項(xiàng)目的教程圖解

    這篇文章主要介紹了Idea 2020.2 創(chuàng)建web、Spring項(xiàng)目的教程,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-08-08

最新評論

石狮市| 永昌县| 蒙自县| 东山县| 宝鸡市| 沙河市| 阳信县| 民县| 泸定县| 定西市| 临江市| 西林县| 榆社县| 迁西县| 汉中市| 奉节县| 临澧县| 吉林省| 彭泽县| 五台县| 楚雄市| 乐昌市| 卓资县| 玛曲县| 固原市| 洪江市| 全南县| 枣强县| 临洮县| 肇州县| 绿春县| 肇东市| 元谋县| 如东县| 晋宁县| 溆浦县| 东乡| 云南省| 怀远县| 宁陵县| 高雄县|