В моем проекте следующая структура бина.
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;
}
У меня похожая структура для клиентов и услуг. Один родитель и несколько реализаций. Мое приложение является промежуточным приложением. Я не знаю, какие объекты времени выполнения наше приложение получает от других вызовов веб-сервисов (модель Bean одинакова для всех приложений). Список может содержать любую реализацию. Это может быть Account или AccountType1 или AccountType2. То же самое в случае с Сервисом. Родитель будет иметь общие поля, а каждая реализация будет иметь определенные поля. У нас будет новый поток для каждого нового клиента, то есть потребителя. Также поле требования отличается. Таким образом, нам нужно иметь отдельный CustomerProfile и соответствующие сопоставители аккаунтов и сервисов. Теперь для 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?