如何用ModelMapper处理同属性名不同类型的实体与DTO互转?
用ModelMapper搞定Entity与DTO双向转换(同名属性类型不同场景)
这种同名但属性类型不匹配的映射场景我熟得很,用ModelMapper的**自定义类型转换器(Converter)**就能完美解决,比你现在写的手动转换清爽多了!下面一步步给你实现:
1. 先引入ModelMapper依赖
如果是Maven项目,在pom.xml里加这个依赖(用最新稳定版就行):
<dependency> <groupId>org.modelmapper</groupId> <artifactId>modelmapper</artifactId> <version>3.2.0</version> </dependency>
2. 针对差异属性写自定义转换器
咱们要处理两个属性的双向转换:category(int ↔ String)和color(String ↔ int),分别写对应的Converter:
import org.modelmapper.Converter; import org.modelmapper.spi.MappingContext; // Animal的int类型category转AnimalDto的String类型category Converter<Integer, String> intToCategoryConverter = new Converter<>() { @Override public String convert(MappingContext<Integer, String> context) { return Category.values()[context.getSource()].toString(); } }; // AnimalDto的String类型category转Animal的int类型category Converter<String, Integer> categoryToIntConverter = new Converter<>() { @Override public Integer convert(MappingContext<String, Integer> context) { return Category.valueOf(context.getSource()).ordinal(); } }; // Animal的String类型color转AnimalDto的int类型color Converter<String, Integer> colorToIntConverter = new Converter<>() { @Override public Integer convert(MappingContext<String, Integer> context) { return Color.valueOf(context.getSource()).ordinal(); } }; // AnimalDto的int类型color转Animal的String类型color Converter<Integer, String> intToColorConverter = new Converter<>() { @Override public String convert(MappingContext<Integer, String> context) { return Color.values()[context.getSource()].toString(); } };
3. 配置ModelMapper并注册转换器
把转换器注册到ModelMapper实例里,顺便配置一下字段访问策略(如果你的实体/DTO用私有属性+getter/setter的话):
import org.modelmapper.ModelMapper; import org.modelmapper.config.Configuration.AccessLevel; ModelMapper modelMapper = new ModelMapper(); // 配置允许访问私有字段,用严格匹配策略避免意外映射 modelMapper.getConfiguration() .setFieldMatchingEnabled(true) .setFieldAccessLevel(AccessLevel.PRIVATE) .setMatchingStrategy(org.modelmapper.MatchingStrategies.STRICT); // 把转换器绑定到对应的类转换场景 modelMapper.addConverter(intToCategoryConverter, Animal.class, AnimalDto.class); modelMapper.addConverter(categoryToIntConverter, AnimalDto.class, Animal.class); modelMapper.addConverter(colorToIntConverter, Animal.class, AnimalDto.class); modelMapper.addConverter(intToColorConverter, AnimalDto.class, Animal.class);
4. 编写简洁的转换方法
现在转换逻辑就超简单了,直接调用ModelMapper的map方法就行,再也不用手动逐个set属性了:
public class AnimalTransformer { // 静态初始化ModelMapper,确保全局只初始化一次 private static final ModelMapper modelMapper; static { modelMapper = new ModelMapper(); // 重复上面的配置和转换器注册逻辑 modelMapper.getConfiguration() .setFieldMatchingEnabled(true) .setFieldAccessLevel(AccessLevel.PRIVATE) .setMatchingStrategy(org.modelmapper.MatchingStrategies.STRICT); // 注册转换器(用Lambda简化写法) Converter<Integer, String> intToCategoryConverter = ctx -> Category.values()[ctx.getSource()].toString(); Converter<String, Integer> categoryToIntConverter = ctx -> Category.valueOf(ctx.getSource()).ordinal(); Converter<String, Integer> colorToIntConverter = ctx -> Color.valueOf(ctx.getSource()).ordinal(); Converter<Integer, String> intToColorConverter = ctx -> Color.values()[ctx.getSource()].toString(); modelMapper.addConverter(intToCategoryConverter, Animal.class, AnimalDto.class); modelMapper.addConverter(categoryToIntConverter, AnimalDto.class, Animal.class); modelMapper.addConverter(colorToIntConverter, Animal.class, AnimalDto.class); modelMapper.addConverter(intToColorConverter, AnimalDto.class, Animal.class); } // Entity转DTO public static AnimalDto animalEntityToDto(Animal animal) { return modelMapper.map(animal, AnimalDto.class); } // DTO转Entity public static Animal animalDtoToEntity(AnimalDto animalDto) { return modelMapper.map(animalDto, Animal.class); } }
为啥这方案比手动转换好?
- 少写重复代码:新增属性时,只要类型匹配或者加个新转换器就行,不用再堆一堆set方法
- 可维护性拉满:转换器可以复用,所有映射配置集中管理
- 符合开闭原则:加新的转换逻辑不用改原有代码,只需要新增Converter就行
内容的提问来源于stack exchange,提问作者Nitish Prajapati
相关产品推荐
相关产品推荐

