当前位置: 首页 > article >正文

BeanUtils.copyProperties,拷贝后,修改target对象的字段,如果保证source对象字段不会变化

问题

我今天碰到一个高德省市区转换的问题,高德省市区数据拉过来的时候,澳门和香港2级下没有3级节点,我想在澳门和香港2级节点下增加一个3级节点,通过BeanUtils.copyProperties后(这里说一句,Spring的BeanUtils在高并发下慢,参考我之前的文章)然后我去修改target对象中treeLevel字段=3和level=city,因为我是从2级节点下copy过来的,我修改之后2级节点的treeLevel和level同样发生了变化,根本原因在于这次拷贝是浅拷贝,source和target中对象引用指向的是同一个对象地址值。

拷贝对象结果

source和target对象结构

@Data
public class GaoDeAreaTreeVO {

    /**
     * 当前节点
     */
    private GaoDeAreaVO gaoDeArea;

    /**
     * 下级节点
     */
    private List<GaoDeAreaTreeVO> children;

}

GaoDeArea

@Data
public class GaoDeAreaVO {

    /**
     * ID
     */
    @ApiModelProperty("ID")
    private Long id;
    /**
     * 节点名称
     */
    @ApiModelProperty("节点名称")
    private String name;
    /**
     * 父级
     */
    @ApiModelProperty(value = "父级")
    private Long parentId;
    /**
     * 全名称 , 号分隔
     */
    @ApiModelProperty(value = "全名称 , 号分隔")
    private String fullName;
    /**
     * 全id  , 号分隔
     */
    @ApiModelProperty(value = "全id  , 号分隔")
    private String treePath;
    /**
     * 树形结构等级
     */
    @ApiModelProperty(value = "树形结构等级")
    private Integer treeLevel;
    /**
     * 地区等级
     */
    @ApiModelProperty(value = "地区等级")
    private String level;
    /**
     * 中心点经度
     */
    @ApiModelProperty(value = "中心点经度")
    private BigDecimal centerLng;
    /**
     * 中心点纬度
     */
    @ApiModelProperty(value = "中心点纬度")
    private BigDecimal centerLat;
    /**
     * 创建时间
     */
    @ApiModelProperty(value = "创建时间")
    private Date createTime;
    /**
     * 首字母
     */
    @ApiModelProperty(value = "首字母")
    private String initials;
}

老代码

当这行代码执行了city.setTreeLevel(3),gaoDeArea这个对象中的treeLevel也发生了变化,原因在于gaoDeArea这个对象拷贝之后,指向的是同一个内存地址值。

// 香港澳门特殊处理 补全city一级(用省一级的信息补全节点)
        GaoDeAreaTreeVO areaTreeVO = categoryTreeVOList.get(0);
        List<GaoDeAreaTreeVO> childCategoryList = areaTreeVO.getChildren();
        for (GaoDeAreaTreeVO tree : childCategoryList) {
            GaoDeAreaVO gaoDeArea = tree.getGaoDeArea();
            if (HK_CODE.equals(gaoDeArea.getId()) || MC_CODE.equals(gaoDeArea.getId())) {
                GaoDeAreaTreeVO temp = new GaoDeAreaTreeVO();
                BeanUtils.copyProperties(tree, temp);
                GaoDeAreaVO city = temp.getGaoDeArea();
                city.setTreeLevel(3);
                city.setLevel("city");
                tree.setChildren(Collections.singletonList(temp));
            }

解决办法

第一种办法

手动set,我的字段太多了,我不想set,这种办法我直接不考虑,丢。

第二种办法

我在拷贝GaoDeAreaTreeVO 这个对象的时候,gaoDeArea这个字段我忽略掉,不拷贝,然后我单独拷贝这个gaoDeArea,然后在设置到GaoDeAreaTreeVO对象的gaoDeArea字段上,完美解决。

// 香港澳门特殊处理 补全city一级(用省一级的信息补全节点)
        GaoDeAreaTreeVO areaTreeVO = categoryTreeVOList.get(0);
        List<GaoDeAreaTreeVO> childCategoryList = areaTreeVO.getChildren();
        for (GaoDeAreaTreeVO tree : childCategoryList) {
            GaoDeAreaVO gaoDeArea = tree.getGaoDeArea();
            if (HK_CODE.equals(gaoDeArea.getId()) || MC_CODE.equals(gaoDeArea.getId())) {
                GaoDeAreaTreeVO temp = new GaoDeAreaTreeVO();
                // 忽略掉gaoDeArea
                BeanUtil.copyProperties(tree, temp, "gaoDeArea");
                // 单独拷贝
                GaoDeAreaVO city = new GaoDeAreaVO();
                BeanUtil.copyProperties(gaoDeArea, city);
                city.setTreeLevel(3);
                city.setLevel("city");
                // 再设置到GaoDeAreaTreeVO 这个对象当中
                temp.setGaoDeArea(city);
                tree.setChildren(Collections.singletonList(temp));
            }
        }

http://www.kler.cn/a/392734.html

相关文章:

  • 【论文阅读笔记】IC-Light
  • YOLO原理讲解
  • 2021-04-08 VSC++: 降序折半查找。
  • SpringCloud 系列教程:微服务的未来(二)Mybatis-Plus的条件构造器、自定义SQL、Service接口基本用法
  • android sqlite 数据库简单封装示例(java)
  • 一次成功流水账-RBDL库的安装与验证
  • 2024年9月 GESP CCF C++六级编程能力等级考试认证真题
  • Jailbreaking ChatGPT via Prompt Engineering: An Empirical Study
  • 手术机器人:精准医疗的新选择
  • blind-watermark - 水印绑定
  • 大数据新视界 -- 大数据大厂之 Impala 在大数据架构中的性能优化全景洞察(上)(13/30)
  • CSS Modules中的 :global
  • 矩阵的各种计算:乘法、逆矩阵、转置、行列式等——基于Excel实现
  • 遇到Word打不开,WPS可以打开的解决办法
  • ES6字符串的新增方法
  • 微服务架构面试内容整理-API 网关-Gateway
  • (68)希尔伯特变换、解析信号,与瞬时幅度、频率和相位的提取的MATLAB仿真
  • 《C陷阱与缺陷》
  • 缓存淘汰策略及其使用场景详解
  • 效率工具-tig的使用
  • 最新的ssl证书有效期只有3个月,ssl到期后如何处理?
  • Java Http 接口对接太繁琐?试试 UniHttp 框架吧
  • Unity Assembly Definition Assembly Definition Reference
  • Python网络爬虫与数据采集实战——网络爬虫的基本流程
  • xcode-select: error: tool ‘xcodebuild‘ requires Xcode, but active developer
  • 随机链表 (Randomized Linked List)、随机树 (Randomized Tree)详细解读