树行结构数据如何优雅的复制整个树

t场景:在开发中经常使用树形结构来组织数据,而在业务中长长出现复制的操作。通常我们复制只修改了用户id,而其他字段都不变变。那么将一棵较大的树复制呢?

表结构如下:

-- 用例库表
CREATE TABLE `venus_case_library` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `name` varchar(100) DEFAULT NULL COMMENT '用例库名',
  `type` tinyint(4) DEFAULT NULL COMMENT '类型,-127~127',
  `app_id` bigint(20) DEFAULT NULL COMMENT '关联应用id',
  `description` varchar(255) DEFAULT NULL COMMENT '用例库描述',
  `is_deleted` varchar(1) DEFAULT 'N' COMMENT '删除标志',
  `creator` bigint(20) DEFAULT NULL,
  `gmt_created` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `modifier` bigint(20) DEFAULT NULL COMMENT '修改人',
  `gmt_modified` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_name_type` (`name`,`type`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

-- 树形结构表
CREATE TABLE `venus_case_tree_copy` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `name` varchar(100) DEFAULT NULL COMMENT '节点名',
  `parent_id` bigint(20) DEFAULT NULL COMMENT '父节点id',
  `type` tinyint(4) DEFAULT NULL COMMENT '节点类型 1 文件夹 2 用例集 3 用例',
  `case_lib_id` bigint(20) DEFAULT NULL COMMENT '用例库id',
  `is_deleted` varchar(1) DEFAULT 'N' COMMENT '删除标志',
  `copy_id` int(11) DEFAULT NULL, -- 该字段时为了复制使用
  PRIMARY KEY (`id`),
  KEY `idx_caseLibId` (`case_lib_id`)
) ENGINE=InnoDB AUTO_INCREMENT=42 DEFAULT CHARSET=utf8;

-- 关联表
CREATE TABLE `venus_text_copy` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `link_table` tinyint(4) NOT NULL COMMENT '连接表id 1:venus_case_tree',
  `link_cid` bigint(20) NOT NULL COMMENT '关联id',
  `text` mediumtext COMMENT '文本',
  PRIMARY KEY (`id`),
  KEY `uk_link` (`link_table`,`link_cid`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=41 DEFAULT CHARSET=utf8;

老的做法:将数据去读到内存中,修改部分数据,然后将数据插入到数据库;这样做出有哪些问题呢

  • 如果有大量的数据,产生多次IO交互
  • 如果在一次读取所有的数据,分批插入,有可能把应用内存打爆;

为了处理以上的问题,我们使用 insert select 的语法,直接在数据库中进行复制操作,变免多个io和内存消耗

  • 修改表结构,在主表中增加 copy_id 字段,记录复制的数据的原id,用来为之后的关连数据insert select 提供支持
  • -- 复制数据,将case_id为4的节点全部复制,新的节点设置的case_id为5
    insert into venus_case_tree_copy (name,parent_id,type,case_lib_id,copy_id,is_deleted) 
    select name,parent_id,type,5,id,'N' from venus_case_tree_copy where case_lib_id=4;
    
    -- 复制关联数据
    insert into venus_text_copy (link_table,link_cid,text)
    select link_table,cid,text from venus_text_copy t1 
    , (select id as cid,copy_id from venus_case_tree_copy where case_lib_id=5 ) t2 
    where t1.link_cid=t2.copy_id
    
    -- 获取关联关系 
       @Select("select t1.id,t2.id as parent_id from " +
                "(select id,parent_id,copy_id from venus_case_tree where case_lib_id=#{libId} and parent_id is not null) t1 " +
                "left JOIN (select id,copy_id from venus_case_tree where case_lib_id=#{libId} ) t2 " +
                "on t1.parent_id=t2.copy_id")
        List<VenusCaseTree> selectNodeRelation(@Param("libId") Long libId);
    -- 刷新关联关系
        @Update("<script>" +
                "<foreach collection='vcts' item='item'  separator=';' >" +
                "update venus_case_tree set parent_id=#{item.parentId} where id=#{item.id}" +
                "</foreach>"+
                "</script>")
        void updateBatch(@Param("vcts") List<VenusCaseTree> vcts);
  • 通过以上四个sql将数据复制完成,完成了主表的复制,已经关联表的复制,并将关联关系同步
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值