【问题标题】:Java - Convert classesJava - 转换类
【发布时间】:2021-07-14 11:49:19
【问题描述】:

我有 2 节课:

public class Customer {
    private String firstname;
    private String lastname;
}

public class Buyer {
    private String firstname;
    private String lastname;
}

我希望这两个类都转换为以下类:

public class CustomerDTO {
   private String firstname;
   private String lastname;
}

我不能为类或其他东西使用通用接口。有没有办法可以使用单个转换器类将 Customer 和 Buyer 都转换为 Customer DTO 类?

【问题讨论】:

  • 鉴于情况 - 不。你要么有两个转换器,要么拉一个通用接口。好吧,当然,如果有必要,您可以通过反射或instanceof 编写自己的hackish 方式,但我不推荐
  • 为什么不能使用接口?定义一个convertableToCustomerDTO 接口并实现一个转换器会很简单。
  • 从 CustomerDTO 扩展这两个类。
  • 由于生成的代码,我无法更改客户或买家
  • @AliMomeni 这是个坏建议。它完全违背了使用 DTO 的目的。

标签: java mapping converters


【解决方案1】:

您可以使用模型映射器,例如查看此http://modelmapper.org/getting-started/

【讨论】:

  • 在不声明两个映射委托的情况下,模型映射器如何提供帮助?
  • 你不必显式定义 delagetes,mapper 会根据变量的类型和名称自动解析变量
  • 是的,当源和目标中的类型和名称相等时就是这种情况。尽管问题以这个为例,但如果你依赖这个魔法,一旦你有不同的命名,转换很快就会失败。我宁愿建议解决BuyerCustomer 具有相同字段但它们在CustomerDTO 中不匹配的问题,因为这将是一个更通用的情况
  • 确实是这个问题。 BuyerCustomer 始终具有相同的字段。但是CustomerDTO 可以有不同的字段。
【解决方案2】:

您无法使用单个转换器类将两个类(CustomerBuyer)转换(映射)为第三个类(CustomerDTO),因为您的没有共享的通用类型(即接口)两个班。 Java 不使用duck typing,因此您不能相信您的类看起来很相似。编译器没有看到。

话虽如此,您至少可以自动生成所需的映射器。一个选项是MapStruct。在您的情况下,映射将很简单(基于documentation):

@Mapper
public interface CustomerMapper {

    CustomerDto toCustomerDto(Customer customer);

    CustomerDto toCustomerDto(Buyer buyer);
}

MapStruct 是一个编译时依赖项:它会在编译时为您生成映射器,因此您可以查看它们。


感谢 Royal Bg 建议使用方法重载 (toCustomerDto) 以获得更清洁的解决方案。

【讨论】:

  • Java 通常不支持鸭子类型,但您可以通过反射强制它。如果您收到Object 作为参数,您可以检查它是否具有某些字段或方法。但是,我根本不建议这样做,只是提一下。因为唯一的好方法是使用两个转换器,所以我会在这里使用某种多态性——方法重载。两种方法都被命名为 toCustomerDto 这样当你得到一个或另一种类型来转换时你不需要输入不同的函数名。
  • 说得好@RoyalBg。我同意反射是解决这个问题的一种不太干净的方法,所以我故意没有提及(但我确实对你的 cmets 投了赞成票 :))
  • 很好的解释,尤其是提到了duck typing。使用鸭子打字,OP 甚至可能不会遇到他们目前面临的问题。
  • 我不是 100% 确定 MapStruct 支持多态 @RoyalBg 所以我使用了不同的方法。这确实是一个更清洁的解决方案。
  • @TasosP。我只在Kotlin中使用过,但应该不会有什么不同,我所有的函数都命名为map(type) :)
【解决方案3】:

这是一个示例代码,您可以将其添加到客户和买方的 DTO 代码中

public UserDTO(Cutomer user) {
        this.id = user.getId();
        this.login = user.getLogin();
        this.firstName = user.getFirstName();
        this.lastName = user.getLastName();
        this.email = user.getEmail();
        this.authorities = user.getAuthorities().stream()
            .map(Authority::getName)
            .collect(Collectors.toSet());
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-09-23
    • 2018-10-05
    • 1970-01-01
    • 2017-04-10
    • 2013-08-17
    • 2015-10-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多