Model Mapper转换DTO到实体时字段值映射错误的解决办法
问题描述
我有一个名为MasterEntity的实体,它与ChildEntity实体是单向一对一关联,数据库映射代码如下:
@Entity(name = "MasterEntity") @Data @AllArgsConstructor @NoArgsConstructor public class MasterEntity { @Id private Integer Id; private String Name; private String Division; @OneToOne @MapsId @JoinColumn(name = "Id") private ChildEntity childEntity; } @Entity(name = "childEntity") @Data @AllArgsConstructor @NoArgsConstructor public class ChildEntity { @Id private Integer Id; private String MatchingName; }
同时我有一个MasterEntityDTO,字段定义如下:
@Builder @Data @AllArgsConstructor @NoArgsConstructor public class MasterEntityDTO { private Integer Id; private String Name; private String Division; }
我尝试用ModelMapper将DTO映射为实体,设置匹配策略为LOOSE(后续计划给DTO添加映射到childEntity的字段),代码如下:
masterEntityDTO.setName("Jonathan"); ModelMapper modelMapper = new ModelMapper(); modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.LOOSE); modelMapper.map(masterEntityDTO, MasterEntity.class);
得到的实体结果却出现错误:MatchingName被填充了Name的值:
Id = null Name = "Jonathan" Division = null Id = null MatchingName = "Jonathan"
尝试过不同ModelMapper配置都无法解决,该如何修复?
解决方案
方法1:显式忽略ChildEntity的MatchingName字段映射
通过添加映射规则,阻止ModelMapper自动匹配Name到MatchingName:
ModelMapper modelMapper = new ModelMapper(); modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.LOOSE); // 显式跳过ChildEntity的MatchingName字段映射 modelMapper.addMappings(mapper -> { mapper.forMember(dest -> dest.getChildEntity().setMatchingName(), opt -> opt.skip()); }); MasterEntity masterEntity = modelMapper.map(masterEntityDTO, MasterEntity.class);
方法2:调整匹配策略为STANDARD(推荐)
改用规则更严格的STANDARD策略,它不会把Name和MatchingName错误关联:
ModelMapper modelMapper = new ModelMapper(); modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STANDARD); MasterEntity masterEntity = modelMapper.map(masterEntityDTO, MasterEntity.class);
后续需要给DTO添加ChildEntity相关字段时,再针对性配置映射规则即可。
方法3:自定义字段映射规则
通过TypeMap明确指定DTO到实体的映射字段,避免自动匹配:
ModelMapper modelMapper = new ModelMapper(); modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.LOOSE); TypeMap<MasterEntityDTO, MasterEntity> typeMap = modelMapper.createTypeMap(MasterEntityDTO.class, MasterEntity.class); // 只映射指定字段 typeMap.addMapping(MasterEntityDTO::getId, MasterEntity::setId); typeMap.addMapping(MasterEntityDTO::getName, MasterEntity::setName); typeMap.addMapping(MasterEntityDTO::getDivision, MasterEntity::setDivision); // 不映射childEntity相关字段 typeMap.addMapping(src -> null, MasterEntity::setChildEntity); MasterEntity masterEntity = typeMap.map(masterEntityDTO);
方法4:修改字段命名(如果允许)
如果可以调整实体字段名,把MatchingName改成和DTO无关联的命名(比如ChildName),从根源避免自动匹配问题。
内容的提问来源于stack exchange,提问作者Mortifer
相关产品推荐
相关产品推荐

