6 つの POJO クラス (3 つの DAO と 3 つの DTO) を考えてみましょう。
DAO: "A"、"B"、"C"
DTO: "One"、"Two"、"Three"
public class A {
private int idOfA;
private String name;
private List<B> b;
// getters, setters, etc...
}
public class B {
private int idOfB;
private String name;
private List<C> c;
// getters, setters, etc...
}
public class C {
private int idOfC;
private String name;
// getters, setters, etc...
}
public class One {
private int id;
private String name;
private List<Two> two;
// getters, setters, etc...
}
public class Two {
private int id;
private String name;
private List<Three> Three;
// getters, setters, etc...
}
public class Three {
private int id;
private String name;
// getters, setters, etc...
}
「A」には「B」のリストが含まれています。「B」には「C」のリストが含まれています。
「One」には「Two」のリストが含まれます。"Two" には "Three" のリストが含まれています。
「A」は「A2One」を介して「One」にマップされます。「B」は「B2Two」を介して「Two」にマップされます。「C」は「C2Three」を介して Three にマップされます。
public class A2One extends PropertyMap<A, One> {
@Override
protected void configure() {
map().setId(source.getIdOfA());
map().setName(source.getName());
when(Conditions.isNotNull()).using(new BListConverter()).map(source.getBs()).setTwos(null);
}
}
public class BListConverter extends AbstractConverter<List<B>, List<Two>> {
@Override
protected List<Two> convert(List<B> source) {
List<Two> twos = new ArrayList<Two>(source.size());
for(B b : source) {
Two t = new Two();
t.setId(b.getId());
t.setName(b.getName());
// Ignore list of Cs contained in B for now
twos.add(t);
}
return twos;
}
}
public class B2Two extends PropertyMap<B, Two> {
@Override
protected void configure() {
map().setId(source.getIdOfB());
map().setName(source.getName());
when(Conditions.isNotNull()).using(new CListConverter()).map(source.getCs()).setThrees(null);
}
}
B2Two と C2Three は、A2One と非常によく似たコードを持っています。
だからここに私の質問があります:
現在、「A」と「One」に含まれるリスト間の変換は、カスタム コンバーターを介して行われます (動作します) が、B2Two が実行するはずの同じ操作を繰り返しています (Bs を Twos にマップします)。
プロパティ マップが行っていることを単に再現するコンバーターを作成することなく、リストをマップするときにプロパティ マップ (A2One -> B2Two -> C2Three) をカスケードする方法はありますか?
代替案 1List, List
:正しいプロパティ/型マップに転送するジェネリックを使用してカスタム TypeMap を作成します。
代替案 2 : A2One では、リストに以下を使用します。
mapper.addMappings(new BList2TwoList());
when(Conditions.isNotNull()).withProvider(listProvider).map().setTwos(mapper.map(source.getBs(), List.class));
ListProvider が AbstractProvider を拡張し、新しい ArrayList() を返す場所
選択肢 3 : ???
何か案は?より複雑なマッピングの問題に関するドキュメントは Web サイトで非常に貧弱であり、必ずしも代替フレームワークを探しているわけではありません。代替案が提供される場合、簡単なリファクタリングを可能にする必要があります (したがって、Dozer と Orika は基本的に除外されます)。
前もって感謝します
更新: 執筆時点では、ModelMapper は基本的に機能せず、実際にはリストやマッピングのカスケードをサポートしていないため、リストにすることもできるすべてのオブジェクトに対してマップとコンバーターを作成する必要があります。
さらに、Orika には MapperBase を拡張することで、リファクタリングしやすいマッピングがあることがわかりました。さらに、Orika は個々の Bean と Bean のリストのマッピングを透過的に処理できます (両方の状況で単一のマッピング ルールを使用)。
更新 2 : Orika では、CustomMapper を使用してコレクションの双方向の深いネストされたマッピングを行うことができます。これにより、双方向マッピングの実装を作成し、それらを他のカスタム マッパーにカスケードできます。A2One は B2Two のインスタンスを保持し、「A」に含まれる「B」をマッピングするときにそれを透過的に使用します。