1. 概要

このチュートリアルでは、ModelMapperフレームワークを使用してさまざまな要素タイプのリストをマップする方法を説明します。 これには、さまざまなタイプのデータをあるリストから別のリストに変換するソリューションとしてJavaの汎用タイプを使用することが含まれます

2. モデルマッパー

ModelMapperの主な役割は、データ変換オブジェクト(DTO)と呼ばれる1つのオブジェクトモデルが別のオブジェクトモデルにどのようにマップされるかを決定することにより、オブジェクトをマップすることです。

ModelMapper を使用するには、まずpom.xmlに依存関係を追加します。

<dependency> 
    <groupId>org.modelmapper</groupId>
    <artifactId>modelmapper</artifactId>
    <version>2.3.7</version>
</dependency>

2.1. 構成

ModelMapperは、マッピングプロセスを簡素化するためのさまざまな構成を提供します。 構成内の適切なプロパティを有効または無効にすることにより、構成をカスタマイズしますそれはです fieldMatchingEnabledプロパティをtrueに設定し、プライベートフィールドマッチングを許可する一般的な方法

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

そうすることで、ModelMapperはマッピングクラス(オブジェクト)のプライベートフィールドを比較できます。 この構成では、同じ名前のすべてのフィールドが両方のクラスに存在する必要はありません。 いくつかのマッチング戦略が許可されています。 デフォルトでは、標準の照合戦略では、すべてのソースプロパティと宛先プロパティを任意の順序で照合する必要があります。 これは私たちのシナリオに理想的です

2.2. タイプトークン

ModelMapperは、TypeTokenを使用して汎用タイプをマップします。 これが必要な理由を確認するために、IntegerリストをCharacterリストにマップするとどうなるかを見てみましょう。

List<Integer> integers = new ArrayList<Integer>();
integers.add(1);
integers.add(2);
integers.add(3);

List<Character> characters = new ArrayList<Character>();
modelMapper.map(integers, characters);

さらに、文字リストの要素を印刷すると、空のリストが表示されます。 これは、実行時の実行中に型消去が発生するためです。

変更した場合地図使用するための呼び出し TypeToken ただし、次の型リテラルを作成できます。 リスト:

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

コンパイル時に、TokenType匿名の内部ケースはリストを保持しますパラメータタイプ、そして今回は変換が成功しました。

3. カスタムタイプマッピングの使用

Javaのリストは、カスタム要素タイプを使用してマップできます。

たとえば、ユーザーエンティティのリストUserDTOリストにマップするとします。 これを実現するために、各要素のマップを呼び出します:

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

もちろん、もう少し作業を行うことで、汎用のパラメーター化されたメソッドを作成できます。

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

では、代わりにを実行できます。

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

4. タイプマップとプロパティマッピング

リストやセットなどの特定のプロパティをUser-UserDTOモデルに追加できます。 TypeMap は、これらのプロパティのマッピングを明示的に定義するためのメソッドを提供します。 TypeMapオブジェクトは、特定のタイプ(クラス)のマッピング情報を格納します:

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

UserList クラスには、Userのコレクションが含まれています。 ここで、w eこのコレクションのユーザー名のリストをプロパティリストにマップする UserListDTOクラス。 これを達成するために、 最初に作成します UsersListConverter クラスとそれを渡すリストリストなので 変換用のパラメータタイプ:

public class UsersListConverter extends AbstractConverter<List<User>, List<String>> {

    @Override
    protected List<String> convert(List<User> users) {

        return users
          .stream()
          .map(User::getUsername)
          .collect(Collectors.toList());
    }
}

作成されたTypeMapオブジェクトから、 プロパティマッピングを明示的に追加します UsersListConverter クラスのインスタンスを呼び出すことによって:

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

addMappingsメソッド内で、式マッピングを使用すると、ラムダ式を使用してソースからデスティネーションのプロパティを定義できます。 最後に、ユーザーのリストを結果のユーザー名のリストに変換します。

5. 結論

このチュートリアルでは、ModelMapperで汎用タイプを操作してリストをマッピングする方法について説明しました。利用できます TypeToken、 ジェネリック型マッピング、およびプロパティマッピングオブジェクトリストタイプを作成して作成するには複雑なマッピング。

この記事の完全なソースコードは、GitHubから入手できます。