gpt4 book ai didi

java - 当泛型类型具有继承结构时,如何在 Mapstruct 中映射集合?

转载 作者:太空宇宙 更新时间:2023-11-04 10:04:58 25 4
gpt4 key购买 nike

我的项目中有以下 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 模型在应用程序中是相同的)。列表可以包含任何实现。它可以是Account、AccountType1 或AccountType2。服务也是如此。父级将有公共(public)字段,每个实现将有特定字段。我们将为每个新客户(即消费者)提供新的流程。 field 要求也不同。因此我们需要有单独的 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 属性中定义的所有指定类。它还应该在映射器中查找各个类特定的映射方法。如果找到,则调用它们,否则生成映射方法。这是必需的,因为我与客户和服务有类似的事情。我不想在映射器中包含太多手写代码,并且每个流程都有数十个不同的 CustomerProfileMappers。而且随着每个版本的发布,它们都在不断增加。我已经阅读了 MapStruct 的完整技术文档。但我找不到办法做到这一点。或者这可能是一个新的 FR?

最佳答案

您可以尝试将帐户的开关外部化。

@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, @Context MyMappingContext ctx);

@Mappings{...}
AccountType1 mapAccountType1(AccountType1 account);

@Mappings{...}
AccountType2 mapAccountType2(AccountType2 account);
}

@Mappings{...}
Account mapBaseAccount(Account account);
}

public class MyMappingContext {

// or whatever component model you prefer
CustomerProfileMapper mapper = CustomerProfileMapper.INSTANCE;

@AfterMaping
public void mapAccount (CustomerProfile source, @MappingTarget CustomerProfile target){

for ( Account account : source.getAccounts() ){

if(account instanceof AccountType1){
mapper.mapAccountType1((AccountType1)account);
}
else if(account instanceof AccountType2){
mapper.mapAccountType2((AccountType2)account);
}
else {
mapper.mapBaseAccount(account);
}
}
}
}

您甚至可以从该上下文回调映射器。如果您愿意,可以将映射器本身的通用行为表示为通用映射器。因此,在 CommonCustomerProfileMapper 中定义签名,并让 CustomerProfileMapper1 继承该签名并定义映射。

关于 MapStruct 中的一项新功能:就像所说的:我不确定对此类功能有多少共同兴趣,但您始终可以发出功能请求。

关于java - 当泛型类型具有继承结构时,如何在 Mapstruct 中映射集合?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53050641/

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