【发布时间】:2019-04-02 16:31:17
【问题描述】:
我的项目中有以下 bean 结构。
public class Account{
// properties
// setters
// getters
}
public class AccountType1 extends Acccount{
// properties
// setters
// getters
}
public class AccountType3 extends Acccount{
// properties
// setters
// getters
}
public class CustomerProfile {
Customer customer;
List<Account> accounts;
List<Service> services;
}
我对客户和服务有类似的结构。一个父级和多个实现。我的应用程序是一个中间件应用程序。我不知道我们的应用程序从其他 Web 服务调用中获得了什么样的运行时对象(Bean 模型在应用程序中是相同的)。 List 可以包含任何实现。它可以是 Account 或 AccountType1 或 AccountType2。服务也是如此。父级将具有公共字段,每个实现将具有特定字段。我们将为每个新客户(即消费者)提供一个新流程。场地要求也不同。所以我们需要有单独的 CustomerProfile 和对应的 Account 和 Service 映射器。现在对于 client1,他们可能需要通用 Account 或 AccountType1 或 AccountType2 或 AccountTypeN 或所有这些。所以代码应该是通用的,就像我在配置中给 {AccountType1.class, AccounTypeN.class} 的任何类型的类一样,它应该只从列表中映射这些对象。由于 AccountType1 扩展了 Account,它还应该处理父类字段。我目前正在这样做。
@Mapper(config = GlobalConfig.class)
public interface CustomerProfileMapper{
@Mappings({
@Mapping( target = "customer", source = "customer"),
@Mapping( target = "accounts", source = "accounts"),
@Mapping( target = "services", source = "services")
})
CustomerProfile mapCustomerProfile(CustomerProfile customerProfile);
@IterableMapping(qualifiedByName = "mapAccount")
List<Account> mapAccounts(List<Account> accounts);
@Named("mapAccount")
default Account mapAccount (Account account){
if(account instanceof AccountType1){
mapAccountType1((AccountType1)account);
}
else if(account instanceof AccountType2){
mapAccountType2((AccountType2)account);
}
else {
mapBaseAccount(account);
}
}
@Mappings{...}
AccountType1 mapAccountType1(AccountType1 account);
@Mappings{...}
AccountType2 mapAccountType2(AccountType2 account);
}
@Mappings{...}
Account mapBaseAccount(Account account);
}
但是此代码将是多余的,因为我必须为不同的 CustomerProfileMappers 的每个流编写。我希望代码是通用的并且可以用作配置。可重用性是这里的关注点。如何解决这个问题?基本上我想做类似下面的事情。
@IterableMapping( mappingClasses= {AccountType1.class, AccountType2.class, Account.class})
List<Account> mapAccounts(List<Account> accounts);
@Mappings{...}
AccountType1 mapAccountType1(AccountType1 account);
@Mappings{...}
AccountType2 mapAccountType2(AccountType2 account);
}
@Mappings{...}
Account mapBaseAccount(Account account);
所以 mapStruct 应该像我目前处理的那样生成代码。它应该生成映射方法来处理在 mappingClasses 属性中定义的所有指定类。它还应该在映射器中寻找各个类特定的映射方法。如果找到调用它们或者生成映射方法。这是必需的,因为我与客户和服务有类似的事情。我不想在映射器中编写太多手写代码,并且每个流程都有数十个不同的 CustomerProfileMapper。并且随着每个版本的发布而不断增加。我已经阅读了 MapStruct 的完整技术文档。但我找不到办法做到这一点。或者这可能是一个新的 FR?
【问题讨论】:
-
如果你想在你的模块中映射 ypur 对象,你是所有的扩展吗?
-
@Filip 没有收到你的问题。
-
您说您正在构建一个由多个应用程序使用的中间件 abd。是您一方的一个父级的实现还是其他应用程序可以扩展您的父级?
-
我们使用的 Bean 模型在所有客户端(即生产者和消费者)中都是通用的。我的意思是我所说的用例将在我们的应用程序中使用。
-
我更新了描述。请再过一遍。