gpt4 book ai didi

java - 如何自定义 ModelMapper

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:26:30 24 4
gpt4 key购买 nike

我想使用 ModelMapper 将实体转换为 DTO 并返回。大多数情况下它有效,但我如何自定义它。它有很多选择,以至于很难弄清楚从哪里开始。什么是最佳实践?

我会在下面自己回答,但如果另一个答案更好,我会接受。

最佳答案

首先这里有一些链接

  • modelmapper getting started
  • api doc
  • blog post
  • random code examples

  • 我对mm的印象是它的设计非常好。代码很扎实,读起来很愉快。但是,文档非常简洁,示例很少。 api 也令人困惑,因为似乎有 10 种方法可以做任何事情,并且没有迹象表明您为什么要以一种或另一种方式来做。

    有两种选择: Dozer是最受欢迎的,和 Orika获得良好的易用性评价。

    假设您仍然想使用 mm,以下是我对它的了解。

    主类, ModelMapper , 应该是您的应用程序中的单例。对我来说,这意味着使用 Spring 的 @Bean。对于简单的情况,它开箱即用。例如,假设您有两个类:
    class DogData
    {
    private String name;
    private int mass;
    }

    class DogInfo
    {
    private String name;
    private boolean large;
    }

    使用适当的 setter/getter / setter/getter 。你可以这样做:
        ModelMapper mm = new ModelMapper();
    DogData dd = new DogData();
    dd.setName("fido");
    dd.setMass(70);
    DogInfo di = mm.map(dd, DogInfo.class);

    并且“名称”将从 dd 复制到 di。

    自定义mm的方法有很多种,但首先你需要了解它是如何工作的。

    mm 对象包含每个有序类型对的 TypeMap,例如 将是两个 TypeMap。

    每个 类型图 包含 属性(property) map 带有映射列表。因此,在示例中,mm 将自动创建一个 TypeMap ,其中包含一个具有单个映射的 PropertyMap。

    我们可以这样写
        TypeMap<DogData, DogInfo> tm = mm.getTypeMap(DogData.class, DogInfo.class);
    List<Mapping> list = tm.getMappings();
    for (Mapping m : list)
    {
    System.out.println(m);
    }

    它会输出
    PropertyMapping[DogData.name -> DogInfo.name]

    当您拨打 mm.map() 这就是它的作用,
  • 看看 类型图 还存在,如果没有为 D> 源/目标类型
  • 调用 TypeMap 条件 , 如果它返回 FALSE,则什么都不做并停止
  • 调用 TypeMap 提供商 必要时构造一个新的目标对象
  • 调用 TypeMap 前置转换器 如果它有一个
  • 执行以下操作之一:
  • 如果 TypeMap 有 自定义转换器 ,叫它
  • 或者,生成 属性(property) map (基于 配置标志 加上添加的任何 自定义映射 ),并使用它
    (注意:TypeMap 也有可选的自定义 Pre/PostPropertyConverters,我认为它们会在每次映射之前和之后运行。)
  • 调用 TypeMap 后置转换器 如果它有一个

  • 警告:此流程图是 sort of documented但我不得不猜测很多,所以它可能不完全正确!

    您可以自定义此过程的每个步骤。但最常见的两种是
  • 步骤 5a。 – 编写自定义 TypeMap 转换器,或
  • 步骤 5b。 – 编写自定义属性映射。

  • 这是 的示例自定义 TypeMap 转换器 :
        Converter<DogData, DogInfo> myConverter = new Converter<DogData, DogInfo>()
    {
    public DogInfo convert(MappingContext<DogData, DogInfo> context)
    {
    DogData s = context.getSource();
    DogInfo d = context.getDestination();
    d.setName(s.getName());
    d.setLarge(s.getMass() > 25);
    return d;
    }
    };

    mm.addConverter(myConverter);

    备注 转换器是单向的。如果要将 DogInfo 自定义为 DogData,则必须编写另一个。

    这是 的示例自定义 PropertyMap :
        Converter<Integer, Boolean> convertMassToLarge = new Converter<Integer, Boolean>()
    {
    public Boolean convert(MappingContext<Integer, Boolean> context)
    {
    // If the dog weighs more than 25, then it must be large
    return context.getSource() > 25;
    }
    };

    PropertyMap<DogData, DogInfo> mymap = new PropertyMap<DogData, DogInfo>()
    {
    protected void configure()
    {
    // Note: this is not normal code. It is "EDSL" so don't get confused
    map(source.getName()).setName(null);
    using(convertMassToLarge).map(source.getMass()).setLarge(false);
    }
    };

    mm.addMappings(mymap);

    pm.configure 函数真的很时髦。这不是实际代码。是假的EDSL code以某种方式被解释。例如,setter 的参数是不相关的,它只是一个占位符。你可以在这里做很多事情,比如
  • 何时(条件)。 map (getter)。setter
  • when(condition).skip().setter – 安全地忽略字段。
  • using(converter).map(getter).setter – 自定义字段转换器
  • with(provider).map(getter).setter – 自定义字段构造函数

  • 备注 自定义映射会添加到默认映射中,因此您不需要,例如,指定
                map(source.getName()).setName(null);

    在您的自定义 PropertyMap.configure() 中。

    在这个例子中,我必须写一个 转换器 将整数映射到 boolean 值。在大多数情况下,这不是必需的,因为 mm 会自动将 Integer 转换为 String 等。

    我听说你也可以创建映射 using Java 8 lambda表达式。我试过了,但我无法弄清楚。

    最终建议和最佳实践

    默认情况下 mm 使用 MatchingStrategies.STANDARD这是危险的。它很容易选择错误的映射并导致奇怪的、难以发现的错误。如果明年其他人向数据库添加一个新列会怎样?所以不要这样做。确保使用 STRICT 模式:
        mm.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);

    始终编​​写单元测试并确保所有映射都经过验证。
        DogInfo di = mm.map(dd, DogInfo.class);
    mm.validate(); // make sure nothing in the destination is accidentally skipped

    使用 mm.addMappings() 修复任何验证失败如上图所示。

    将所有映射放在创建 mm 单例的中心位置。

    关于java - 如何自定义 ModelMapper,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44534172/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com