4

ビジネス オブジェクトをエンティティにマッピングしますが、エンティティの構造がビジネス オブジェクトと異なる場合があります。
BO はエンティティの内部構造について何も知る必要がないため、文字列としてuserCategoriesビジネス オブジェクトに保存されます。RecipeBoこれらの文字列は のリレーションにマップする必要がありRecipeRecipeUserCategoryRelそれに加えて、別のフィールドもこれにマップする必要がありuserIdます。RecipeBoRecipeUserCategoryRel

私のアプローチ(これは機能します)は、ラッパーを作成し、手作業でリレーションを手動で作成することですが、これはいじくり回すように見えます:

public class BoMapper
{
    private final static ModelMapper modelMapper = new ModelMapper();

    static
    {
        modelMapper.addMappings(new IngredientMap());
    }

    public static void map(Object from, Object to)
    {
        modelMapper.map(from, to);

        if (from instanceof RecipeBo && to instanceof Recipe)
        {
            RecipeBo recipeBo = (RecipeBo)from;
            List<String> userCategories = recipeBo.getUserCategories();
            List<RecipeUserCategoryRel> recipeUserCategoryRels = new ArrayList<>();

            for (String userCategory : userCategories)
            {
                recipeUserCategoryRels.add(new RecipeUserCategoryRel(userCategory, recipeBo.getUserId()));
            }

            Recipe recipe = (Recipe)to;

            recipe.setRecipeUserCategoryRels(recipeUserCategoryRels);
        }
    }
}

私がBoMapperで行っていること、例えばコンバーターなどを使用することのより良いアプローチはありますか? 難しいのは、リストの各要素をマップし、userIdフィールドも追加することです。

4

1 に答える 1

3

問題

リストから直接ではなく、他の階層から userId を取得しているため、これは複雑な状況です。ModelMapper は List を List にマップしますが、ModelMapper を LOOSE として構成しないと機能しません。

modelMapper.getConfiguration()
  .setMatchingStrategy(MatchingStrategies.LOOSE);

とにかく、ModelMapper をそのように構成する場合 (LOOSE モード)、List をマップし、クラス RecipeUserCategoryRel の String プロパティに入れます (この場合、たとえば、userCategory が String であり、userId が String ではないことを考慮すると) 他の(よくわかりません)nullになると思います。

解決

問題の解決策は、 Converter を作成して ModelMapper インスタンスに追加することだと思います。

  • RecipeBO (ソース) -> レシピ (宛先)

コードは次のようになります。

ModelMapper mapper = new ModelMapper();

Converter<RecipeBO, Recipe> converter = new Converter<RecipeBO,
 Recipe>() {

        @Override
        public Recipe convert(MappingContext<RecipeBO, Recipe> context) {
            RecipeBO source = context.getSource();
            Recipe destination = new Recipe();

            List<String> userCategoryValues = source.getUserCategories();
            List<RecipeUserCategoryRel> userCategoryToMap = new ArrayList<RecipeUserCategoryRel>();

            for(final String userCategory : userCategoryValues){
                userCategoryToMap.add(new RecipeUserCategoryRel(userCategory,source.getUserId()));
            }
            destination.setRecipeUserCategoryRels(userCategoryToMap);

            //... Map other properties if you need

            return  destination;

        }
    };

    //Option 1
    mapper.createTypeMap(RecipeBO.class, Recipe.class).setConverter(converter);

    //If you add as a converter directly also works (I don't know which one is better, 
    //choose above option (createTypeMap + setConverter) or the next (addConverter)
    //Option 2 -> mapper.addConverter(converter);

私はテストしましたが、動作します!!

次のようなレシピがある場合:

RecipeBO recipe = new RecipeBO();
recipe.setUserId("1");
String values[] = new String[] { "abc", "klm", "xyz", "pqr" };

List<String> list = Arrays.asList(values);
recipe.setUserCategories(list);

そして RecipeBO:

 Recipe recipe = new Recipe();
 List<RecipeUserCategoryRel> recipes = new ArrayList<>();
 recipes.add(new RecipeUserCategoryRel("abc", "1"));        
 recipes.add(new RecipeUserCategoryRel("klm", "1"));
 recipes.add(new RecipeUserCategoryRel("xyz", "1"));
 recipes.add(new RecipeUserCategoryRel("pqr", "1"));
 recipe.setRecipeUserCategoryRels(recipes);

RecipeBO を Recipe にマップすると、次のようになります。

Recipe actual = mapper.map(getRecipeBO(), Recipe.class);

次の出力を取得します。

出力:

- RecipeUserCategoryRel(userCategory=abc, userId=1)
- RecipeUserCategoryRel(userCategory=klm, userId=1)
- RecipeUserCategoryRel(userCategory=xyz, userId=1)
- RecipeUserCategoryRel(userCategory=pqr, userId=1)
于 2016-07-28T21:05:09.363 に答える