V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
zealinux
V2EX  ›  Java

[需重构] Java 如何从大对象截取部分字段转为小对象?

  •  
  •   zealinux · 2021-09-22 10:16:28 +08:00 · 2527 次点击
    这是一个创建于 1160 天前的主题,其中的信息可能已经有所发展或是发生改变。

    比如这段代码: 从Goods这个大对象( 20+字段,对应 DB 中 Goods 表)列表里截取( 5 个字段)生成小对象列表( GoodsApiVo )进行返回, 工程里到处都有这样的样板代码。

    假设以后小对象需要获取 10 个字段, 那岂不是,map 那一行写很长很长?

    希望有什么简单的方法进行重构。

    // List<Goods> goods ==>  List<GoodsApiVo> goodsApiVos
    
    List<GoodsApiVo> goodsApiVos = goods.stream()
            .map((Goods s) -> new GoodsApiVo(s.getBarcode(), s.getName(), s.getPrice(), s.getCreateTime(), s.getUpdateTime()))
            .collect(Collectors.toList());
    
    17 条回复    2021-09-30 08:51:04 +08:00
    eltria
        1
    eltria  
       2021-09-22 10:23:47 +08:00
    大对象小对象字段同名的话,cglib beancopier 就行了,而且对性能的影响是最小化的
    aichunya
        2
    aichunya  
       2021-09-22 10:25:21 +08:00
    BeanUtils.copyProperties(Object source, Object target, String... ignoreProperties);
    这个,可以把不需要的字段 ignore?
    chendy
        3
    chendy  
       2021-09-22 10:28:58 +08:00
    使用 mapstruct 这类的工具做转换,节省一部分代码量
    另外除非涉及到数据安全或者性能之类的问题,返回所有字段也不是什么坏事。。。
    dqzcwxb
        4
    dqzcwxb  
       2021-09-22 10:31:25 +08:00
    手动 set 性能最高且方便维护,改成链式 set 即可
    wolfie
        5
    wolfie  
       2021-09-22 10:37:45 +08:00
    mapstruct + 1
    EscYezi
        6
    EscYezi  
       2021-09-22 10:38:24 +08:00 via iPhone
    mapstruct+1
    Leviathann
        7
    Leviathann  
       2021-09-22 10:46:06 +08:00
    感觉没什么问题,或者你写个静态方法放到 dto 的 class 里
    这部分逻辑本来就是不能少的,换别的方法也只是藏起来,如果有问题更不好找
    youngxhui
        8
    youngxhui  
       2021-09-22 11:16:32 +08:00
    Spring 的 Beauntils 可以方便的实现两个对象之间的属性拷贝
    cubecube
        9
    cubecube  
       2021-09-22 11:17:03 +08:00
    挨个 set 也不费劲。
    还没有黑盒子,bean copy 慢不说,copy 深度还得自己去研究下啥的,没啥太大收益。
    aragakiyuii
        10
    aragakiyuii  
       2021-09-22 11:22:15 +08:00
    new GoodsApiVo(Goods s) 这种比上面那个好点吧,改的话就直接去改构造函数里的东西就行了
    HiShan
        11
    HiShan  
       2021-09-22 11:43:46 +08:00
    实现一个方法:public GoodApiVo toGoodApiVo(String... fields)
    List<GoodsApiVo> goodsApiVos = goods.stream().map((Good::toGoodApiVo).collect(Collectors.toList());
    wowo243
        12
    wowo243  
       2021-09-22 11:50:37 +08:00
    beanUtils 或者 json 序列化再反序列化一下实现拷贝
    siweipancc
        13
    siweipancc  
       2021-09-22 12:08:53 +08:00 via iPhone
    hutool 工具有个 toBean 方法,最快最简单的方法了
    passerbytiny
        14
    passerbytiny  
       2021-09-22 13:23:49 +08:00 via Android
    并不是所有类似代码都能提取成公共处理。从 A 表中提取 5 个字段生成 A2 对象、从 B 表中提取 5 个字段生成 B2 对象,这两个操作
    passerbytiny
        15
    passerbytiny  
       2021-09-22 13:26:14 +08:00 via Android
    就像张三、李四吃饭一样,看起来是类似的但却是实在在是两码事。

    绝对的不复制粘贴代码,是过度模式,楼主贴的代码就是最合适的 2 处理方式。
    AoEiuV020
        16
    AoEiuV020  
       2021-09-22 16:06:53 +08:00
    条件允许的话考虑继承,或者用接口,
    比如 Goods implements GoodsApiVo,
    INTOX8O
        17
    INTOX8O  
       2021-09-30 08:51:04 +08:00
    Jackson 的 ObjectMapper.convertValue() 字段名一样可以直接转换,不一样可以配置模糊匹配或者自定义 Jsonserializer
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5710 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 35ms · UTC 08:55 · PVG 16:55 · LAX 00:55 · JFK 03:55
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.