Mappatura di elenchi con ModelMapper

1. Panoramica

In questo tutorial, spiegheremo come mappare elenchi di diversi tipi di elementi utilizzando il framework ModelMapper. Questo implica l'utilizzo di tipi generici in Java come soluzione per convertire diversi tipi di dati da un elenco a un altro .

2. Model Mapper

Il ruolo principale di ModelMapper è mappare gli oggetti determinando il modo in cui un modello a oggetti viene mappato a un altro chiamato Data Transformation Object (DTO).

Per poter utilizzare ModelMapper, iniziamo aggiungendo la dipendenza al nostro pom.xml :

 org.modelmapper modelmapper 2.3.7 

2.1. Configurazione

ModelMapper fornisce una varietà di configurazioni per semplificare il processo di mappatura. Personalizziamo la configurazione abilitando o disabilitando le proprietà appropriate nella configurazione. È pratica comune impostare la proprietà fieldMatchingEnabled su true e consentire la corrispondenza dei campi privati :

modelMapper.getConfiguration() .setFieldMatchingEnabled(true) .setFieldAccessLevel(Configuration.AccessLevel.PRIVATE); 

In questo modo, ModelMapper può confrontare i campi privati ​​nelle classi di mappatura (oggetti). In questa configurazione, non è strettamente necessario che tutti i campi con lo stesso nome esistano in entrambe le classi. Sono consentite diverse strategie di abbinamento. Per impostazione predefinita, una strategia di corrispondenza standard richiede che tutte le proprietà di origine e di destinazione debbano corrispondere in qualsiasi ordine. Questo è l'ideale per il nostro scenario .

2.2. Digita Token

ModelMapper utilizza TypeToken per mappare i tipi generici. Per vedere perché è necessario, vediamo cosa succede quando mappiamo un elenco di numeri interi a un elenco di caratteri :

List integers = new ArrayList(); integers.add(1); integers.add(2); integers.add(3); List characters = new ArrayList(); modelMapper.map(integers, characters);

Inoltre, se stampiamo gli elementi della lista dei caratteri vedremmo una lista vuota. Ciò è dovuto al verificarsi della cancellazione del tipo durante l'esecuzione del runtime.

Se modifichiamo la nostra chiamata alla mappa per utilizzare TypeToken , tuttavia, possiamo creare un tipo letterale per List :

List characters = modelMapper.map(integers, new TypeToken
    
     () {}.getType());
    

In fase di compilazione, il case interno anonimo TokenType conserva il tipo di parametro List e questa volta la nostra conversione ha esito positivo.

3. Utilizzo della mappatura dei tipi personalizzata

Gli elenchi in Java possono essere mappati utilizzando tipi di elementi personalizzati.

Ad esempio, supponiamo di voler mappare un elenco di entità utente a un elenco UserDTO . Per ottenere ciò, chiameremo map per ogni elemento:

List dtos = users .stream() .map(user -> modelMapper.map(user, UserDTO.class)) .collect(Collectors.toList());

Naturalmente, con un po 'di lavoro in più, potremmo creare un metodo parametrizzato di uso generale:

 List mapList(List source, Class targetClass) { return source .stream() .map(element -> modelMapper.map(element, targetClass)) .collect(Collectors.toList()); }

Quindi, allora, potremmo invece fare:

List userDtoList = mapList(users, UserDTO.class);

4. Digitare Map e Property Mapping

È possibile aggiungere proprietà specifiche come elenchi o set al modello User-UserDTO . TypeMap fornisce un metodo per definire esplicitamente la mappatura di queste proprietà. L' oggetto TypeMap memorizza le informazioni di mappatura di tipi (classi) specifici:

TypeMap typeMap = modelMapper.createTypeMap(UserList.class, UserListDTO.class);

La classe UserList contiene una raccolta di User s. Qui, vogliamo mappare l'elenco dei nomi utente da questa raccolta all'elenco delle proprietà della classe UserListDTO . Per ottenere ciò, creeremo la prima classe UsersListConverter e la passeremo List e List come tipi di parametri per la conversione:

public class UsersListConverter extends AbstractConverter
    
      { @Override protected List convert(List users) { return users .stream() .map(User::getUsername) .collect(Collectors.toList()); } }
    

Dall'oggetto TypeMap creato aggiungiamo esplicitamente Property Mapping richiamando un'istanza della classe UsersListConverter :

 typeMap.addMappings(mapper -> mapper.using(new UsersListConverter()) .map(UserList::getUsers, UserListDTO::setUsernames));

All'interno del metodo addMappings , una mappatura di espressioni ci consente di definire le proprietà da sorgente a destinazione con espressioni lambda. Infine, converte l'elenco degli utenti nell'elenco risultante di nomi utente.

5. conclusione

In questo tutorial, abbiamo spiegato come vengono mappati gli elenchi manipolando i tipi generici in ModelMapper . Possiamo fare uso di TypeToken, mapping dei tipi generici e mapping delle proprietàper creare tipi di elenchi di oggetti e creare mappature complesse.

Il codice sorgente completo per questo articolo è disponibile su GitHub.