当前位置: 代码网 > it编程>编程语言>Java > 在SpringBoot+MyBatis中优雅处理多表数据清洗的实现步骤

在SpringBoot+MyBatis中优雅处理多表数据清洗的实现步骤

2025年03月06日 Java 我要评论
问题背景在实际业务中,我们常会遇到数据冗余问题。例如,一个公司表(sys_company)中存在多条相同公司名的记录,但只有一条有效(del_flag=0),其余需要删除。删除前需将关联表(如合同草稿

问题背景

在实际业务中,我们常会遇到数据冗余问题。例如,一个公司表(sys_company)中存在多条相同公司名的记录,但只有一条有效(del_flag=0),其余需要删除。删除前需将关联表(如合同草稿表、发票表等)的外键字段(如purchaser_id)替换为保留记录的id。这类问题通常涉及多表、多字段的动态更新,如何高效且安全地实现?

解决方案

我们将通过以下步骤实现:

  1. 配置化驱动:用配置类声明需要处理的表和字段,避免硬编码。
  2. 动态sql更新:通过mybatis xml实现批量更新和删除。
  3. 事务一致性:确保所有操作原子化执行。

实现步骤

1. 定义实体类

companyretainedinfo:封装需保留的公司信息

import lombok.data;

@data
public class companyretainedinfo {
    private string companyname;   // 公司名称
    private long retainedid;      // 需保留的公司id(del_flag=0的记录)
    private string retainedname;  // 需保留的公司名称(与companyname一致)
}

• 作用:映射查询结果,传递保留记录的id和名称。
• lombok@data 自动生成getter/setter和tostring()方法。

2. 定义配置类

tableconfig:声明需处理的表和外键关系

public class tableconfig {
    private string tablename;    // 表名(如contract_draft)
    private string idcolumn;     // 外键id字段(如purchaser_id)
    private string namecolumn;  // 名称字段(如purchaser_name,可能为null)

    // 构造器 + getter/setter
    public tableconfig(string tablename, string idcolumn, string namecolumn) {
        this.tablename = tablename;
        this.idcolumn = idcolumn;
        this.namecolumn = namecolumn;
    }
}

3. 编写mybatis mapper接口

companycleanmapper:定义数据操作接口(无注解,纯xml映射

@mapper
public interface companycleanmapper {
    // 查询需保留的公司信息(del_flag=0)
    list<companyretainedinfo> selectretainedcompanies();

    // 根据公司名查询待删除的id列表(del_flag!=0)
    list<long> selectidstodelete(string companyname);

    // 更新关联表的外键引用
    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. 实现xml映射文件

companycleanmapper.xml:定义动态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>

    <!-- 动态更新外键引用 -->
    <update id="updateforeignkeys">
        update ${config.tablename}
        set
            <choose>
                <when test="config.namecolumn != null">
                    <!-- 同时更新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. 服务层实现

companycleanservice:配置化驱动批量处理

@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. 更新所有关联表的外键引用
                table_configs.foreach(config -> 
                    companycleanmapper.updateforeignkeys(
                        config, 
                        info.getretainedid(), 
                        info.getretainedname(), 
                        idstodelete
                    )
                );
                
                // 4. 删除冗余公司记录
                companycleanmapper.deletecompanies(idstodelete);
            }
        }
    }
}

关键设计说明

  1. 实体类与数据映射
    • companyretainedinfo 通过别名(as retainedid)直接映射查询结果,避免额外转换。
    • companyname 和 retainedname 字段值相同,但保留后者以明确语义。

  2. xml动态sql优势
    • <choose>:根据配置动态决定是否更新名称字段。
    • <foreach>:自动展开id列表为in (id1, id2...),支持批量操作。
    • ${}占位符:安全引用配置的表名和字段名(非用户输入,无注入风险)。

  3. 事务与性能优化
    • @transactional:保证“更新外键”和“删除公司”操作的原子性。
    • 索引建议:对sys_company.company_name和关联表的外键字段添加索引。

总结

通过 实体类封装配置化表关系 和 mybatis动态sql,我们实现了一套可扩展的多表数据清洗方案。这种模式的核心在于:

  1. 抽象变化部分:将表和字段的差异收敛到配置类中。
  2. 复用不变逻辑:批量更新和删除操作由统一服务驱动。
  3. 最小化侵入性:新增表只需修改配置,无需改动核心逻辑。

该方案适用于用户中心、商品系统等存在外键关联的冗余数据处理场景,读者可结合实际需求调整配置和sql逻辑。

以上就是在springboot+mybatis中优雅处理多表数据清洗的实现步骤的详细内容,更多关于springboot mybatis多表数据清洗的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com