MapStructを使用したカスタムマッパー

1. 概要

この記事では、https://www.baeldung.com/mapstruct [MapStruct library]でカスタムマッパーを使用する方法を学習します。
  • MapStructライブラリは、Java Beanタイプ間のマッピングに使用されます*。 MapStruct でカスタムマッパーを使用することにより、 デフォルトのマッピング方法をカスタマイズできます。

2. Mavenの依存関係

Maven _pom.xml_にhttps://search.maven.org/search?q=g:org.mapstruct%20a:mapstruct-jdk8[mapstruct-jdk8]ライブラリを追加しましょう。
<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct-jdk8</artifactId>
    <version>1.3.0.Final</version>
</dependency>
プロジェクトの_target folder_内に自動生成されたメソッドを表示するには、_annotationProcessorPaths_を_maven-compiler-plugin_プラグインに追加する必要があります。
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.5.1</version>
    <configuration>
        <source>1.8</source>
        <target>1.8</target>
        <annotationProcessorPaths>
            <path>
                <groupId>org.mapstruct</groupId>
                <artifactId>mapstruct-processor</artifactId>
                <version>1.3.0.Final</version>
            </path>
        </annotationProcessorPaths>
    </configuration>
</plugin>

3. カスタムマッパー

カスタムマッパーは、特定の変換要件を解決するために使用されます。 これを実現するには、変換を行うメソッドを定義する必要があります。 次に、メソッドについてMapStructに通知する必要があります。 最後に、MapStructはメソッドを呼び出して、ソースからターゲットへの変換を行います。
たとえば、ユーザーのボディマスインデックス(BMI)レポートを計算するアプリがあるとします。 BMIを計算するには、ユーザーの体の値を収集する必要があります。 帝国単位をメートル単位に変換するには、カスタムマッパーメソッドを使用できます。
MapStructでカスタムマッパーを使用する方法は2つあります。 * _ @ Mapping_アノテーションの_qualifiedByName_プロパティ内に入力してカスタムメソッドを呼び出すか、そのためのアノテーションを作成できます。*
開始する前に、帝国の値を保持するDTOクラスを定義する必要があります。
public class UserBodyImperialValuesDTO {
    private int inch;
    private int pound;
    // constructor, getters, and setters
}
次に、メトリック値を保持するDTOクラスを定義しましょう。
public class UserBodyValues {
    private double kilogram;
    private double centimeter;
    // constructor, getters, and setters
}

3.1. メソッドを使用したカスタムマッパー

カスタムマッパーの使用を開始するには、_ @ Mapper_アノテーションを使用してインターフェイスを作成しましょう。
@Mapper
public interface UserBodyValuesMapper {
    //...
}
次に、必要な戻り値の型と変換する必要のある引数を使用してカスタムメソッドを作成します。 カスタムのマッパーメソッドについてMapStructに通知するには、valueパラメーターで@_Named_アノテーションを使用する必要があります。
@Mapper
public interface UserBodyValuesMapper {

    @Named("inchToCentimeter")
    public static double inchToCentimeter(int inch) {
        return inch * 2.54;
    }

    //...
}
そして最後に、マッパーインターフェイスメソッドを_ @ Mapping_アノテーションで定義しましょう。 この注釈内で、ソースタイプ、ターゲットタイプ、および使用するメソッドについてMapStructに通知します。
@Mapper
public interface UserBodyValuesMapper {
    UserBodyValuesMapper INSTANCE = Mappers.getMapper(UserBodyValuesMapper.class);

    @Mapping(source = "inch", target = "centimeter", qualifiedByName = "inchToCentimeter")
    public UserBodyValues userBodyValuesMapper(UserBodyImperialValuesDTO dto);

    @Named("inchToCentimeter")
    public static double inchToCentimeter(int inch) {
        return inch * 2.54;
    }
}
カスタムマッパーをテストしてみましょう。
UserBodyImperialValuesDTO dto = new UserBodyImperialValuesDTO();
dto.setInch(10);

UserBodyValues obj = UserBodyValuesMapper.INSTANCE.userBodyValuesMapper(dto);

assertNotNull(obj);
assertEquals(25.4, obj.getCentimeter(), 0);

3.2. 注釈付きのカスタムマッパー

アノテーションでカスタムマッパーを使用するには、_ @ Named_アノテーションの代わりにアノテーションを定義する必要があります。 次に、@ _ Mapping_アノテーションの_qualifiedByName_ parameter __.__を指定して、新しく作成されたアノテーションについてMapStructに通知する必要があります。
注釈の定義方法を見てみましょう。
@Qualifier
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.CLASS)
public @interface PoundToKilogramMapper {
}
_poundToKilogram_メソッドに_ @ PoundToKilogramMapper_注釈を追加しましょう。
@PoundToKilogramMapper
public static double poundToKilogram(int pound) {
    return pound * 0.4535;
}
それでは、_ @ Mapping_アノテーションを使用してマッパーインターフェイスメソッドを定義しましょう。 マッピングアノテーション内で、使用するソースタイプ、ターゲットタイプ、およびアノテーションクラスについてMapStructに通知します。
@Mapper
public interface UserBodyValuesMapper {
    UserBodyValuesMapper INSTANCE = Mappers.getMapper(UserBodyValuesMapper.class);

    @Mapping(source = "pound", target = "kilogram", qualifiedBy = PoundToKilogramMapper.class)
    public UserBodyValues userBodyValuesMapper(UserBodyImperialValuesDTO dto);

    @PoundToKilogramMapper
    public static double poundToKilogram(int pound) {
        return pound * 0.4535;
    }
}
最後に、カスタムマッパーをテストしましょう。
UserBodyImperialValuesDTO dto = new UserBodyImperialValuesDTO();
dto.setPound(100);

UserBodyValues obj = UserBodyValuesMapper.INSTANCE.userBodyValuesMapper(dto);

assertNotNull(obj);
assertEquals(45.35, obj.getKilogram(), 0);

4. 結論

この記事では、* MapStructライブラリでカスタムマッパーを使用する方法を学びました。*
これらの例とテストの実装は、https://github.com/eugenp/tutorials/tree/master/mapstruct [GitHubの上]で入手できます。