ModelMapper:将集合映射到其他结构的集合

5
我将业务对象映射到实体,有时实体的结构与业务对象不同。
我有一个名为userCategories的业务对象,在RecipeBo中存储为字符串,因为BO不需要知道实体的内部结构。这些字符串需要映射到RecipeRecipeUserCategoryRel的关系中,另外,RecipeBouserId字段也需要映射到此RecipeUserCategoryRel中。
我的方法(有效)是创建一个包装器,手动创建关系,但这看起来像在折腾:
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 字段。

1个回答

4

问题

这是一个复杂的情况,因为您从其他层次结构获取了userId,而不是直接从List中获取。ModelMapper会将List映射到List,但如果您没有将ModelMapper配置为LOOSE,则它将无法正常工作。

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

无论如何,如果您以该方式(LOOSE模式)配置ModelMapper,它将映射List并将其放入Class RecipeUserCategoryRel的String属性中(在此示例中为userCategory,如果它不是String并且考虑到userId不是String,则其他内容可能为空。

解决方案

嗯,我认为解决您的问题的方法是创建一个Converter,并将其添加到您的ModelMapper实例中:

  • RecipeBO(源) -> Recipe(目标)

代码如下:

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);

I get the next Output:

OUTPUT:

- RecipeUserCategoryRel(userCategory=abc, userId=1)
- RecipeUserCategoryRel(userCategory=klm, userId=1)
- RecipeUserCategoryRel(userCategory=xyz, userId=1)
- RecipeUserCategoryRel(userCategory=pqr, userId=1)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接