web-dev-qa-db-ja.com

MapStruct:マッピングアノテーションを強化してカスタムマッパーを定義します

コンテキストは次のとおりです。byteBuddyを使用して、外部構成に基づいてオブジェクトを別のオブジェクトに変換するクラスを動的に生成しています。いくつかの問題が発生したため、MapStructの発見方法である代替手段を見つけたいと思いました。

そこで、単純なマッパーを作成しようとしましたが、注釈をカスタマイズして変換関数を追加する可能性があるかどうかを知りたかったのです。たとえば、私は持っておきたい:

@Mapping(
    source = "mySourceField", 
    sourceType = "String",
    target = "myTargetField",
    targetType = "Integer",
    transformation = {"toInteger", "toSquare"}
),

マッパーの実装では、次のようなものがあります。

 public TypeDest toSiteCatTag(TypeSrc obj) {

    if ( obj == null ) {

        return null;
    }

    TypeDest objDest = new TypeDest();

    objDest.myTargetField = Formatter.toSquare(
        Formatter.toInteger(obj.mySourceField));

    return objDest;
}

誰かがそれを達成するのを手伝ってくれるなら、私は感謝するでしょうし、それは私に多くの時間を節約するでしょう。

前もって感謝します。

10
nbchn

2つのタイプTypeDestTypeSrcが実行時に生成されない場合、つまりそれらがコンパイルされたクラスである場合、望みを達成できます。 MapStructはアノテーションプロセッサであり、Javaコードを生成します。存在しないフィールドをマッピングしようとしている場合や、マッピング方法があいまいな場合など、コンパイル時エラーが発生します。

次のようになります。

_@Mapper
public interface MyMapper {

    @Mapping(source = "mySourceField", target = "myTargetField", qualifiedByName = "myTransformation")// or you can use a custom @Qualifier annotation with qualifiedBy
    TypeDest toSiteCatTag(TypeSrc obj);

    @Named("myTransformation")// or your custom @Qualifier annotation
    default Integer myCustomTransformation(String obj) {
        return Formatter.toSquare(Formatter.toInteger(obj));
    }
}
_

マッパーでカスタムメソッドを使用せずにそれを行う方法がありますが、toIntegerに続いてtoSquare変換を適用するメソッドが必要になります。 FormatterInteger squaredString(String obj)というシグネチャを持つメソッドがある場合。

例えば.

_@Qualifier
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.CLASS)
public @interface SquaredString {}

public class Formatter {

    @SquaredString// you can also use @Named, this is just as an example
    public static Integer squaredString(String obj) {
        return toSquare(toInteger(obj));
    }
    //your other methods are here as well
}
_

次に、マッパーでこれを実行できます。

_@Mapper(uses = { Formatter.class })
public interface MyMapper {

    @Mapping(source = "mySourceField", target = "myTargetField", qualifiedBy = SquaredString.class)
    TypeDest toSiteCatTag(TypeSrc obj);
}
_

qualifedByName/qualifiedが使用されるため、上記の例は特定のマッピングにのみ適用されます。 StringIntegerに変換する別の方法が必要な場合、マッパーまたは_Mapper#uses_のいくつかのクラスのいずれかで署名を使用してメソッドを定義できます。 Integer convertString(String obj)。 MapStructは、StringからIntegerへの変換をこのメソッドに委任します。

修飾子 here を使用したマッピングの詳細についてはリファレンスドキュメントを、 here を使用してマッピング方法の解決に関する詳細を参照してください。

19
Filip