Java中ModelMapper 的高级使用

 更新时间:2022年02月21日 11:57:17   作者:lytao123  
本文主要介绍了Java中ModelMapper 的高级使用,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

ModelMapper 高级使用

  ModelMapper 是一个 Object To Object 的工具,类似于 MapStruct又不同于 MapStruct。主要原因是 ModelMapper 是利用反射的原理实现的 Object To Object。

  ModelMapper 官方API : http://modelmapper.org/user-manual/property-mapping/

使用实例

本实例实现了条件映射、嵌套映射(对象中有对象映射)、自定义属性映射、List 集合映射(对象中有集合映射)、Map集合映射(对象中有集合映射)、忽略映射,默认值设置(ModelMapper 的默认值设置时一不小心就会入坑,如果直接设置默认值,当再赋值转换时,默认值会覆盖赋值的值,所以设置默认值需要结合条件映射)等。
验证了对象属性为集合,集合中还有集合能够使用 ModelMapper 进行转换。不足点是这个实例中没有验证有继承关系时的映射(使用 modelMapper.includeBase(父类1, 父类2) 方法),多个属性映射为一个属性或一个属性映射为多个属性(使用 PropertyMap 转换器)。

  • 使用条件映射设置默认值。当 age/createTime 没有值时设置默认值为18/当前时间,有值时不设置默认值;
  • 嵌套映射,自定义属性映射。Source 的 sourceSon 成员变量 映射到 Destination 的 destinationSon 成员变量;
  • List集合映射。Source 的 listSon 成员变量 映射到 Destination 的 sonList 成员变量;
  • Map集合映射。Source 的 mapSon 成员变量 映射到 Destination 的 sonMap 成员变量;
  • 忽略映射。忽略 Destination 的 excessParam 成员变量,如果不忽略将验证不过,报 org.modelmapper.MappingException: ModelMapper mapping errors;

实体类

(1)BaseClass

@Getter
@Setter
public class BaseClass {

    private String id;
    private String name;

    public BaseClass() {

    }

    public BaseClass(String id, String name) {
        this.id = id;
        this.name = name;
    }
}

(2)SouSubClass

@Getter
@Setter
public class SouSubClass {

    private String sonId;
    private String sonName;
    private List<BaseClass> grandSons;

    public SouSubClass() {

    }

    public SouSubClass(String sonId, String sonName) {
        this.sonId = sonId;
        this.sonName = sonName;
    }
}

(3)DestSubClass

@Getter
@Setter
public class DestSubClass {

    private String dsonId;
    private String sonName;
    private String excessParam;
    private List<BaseClass> grandSons;

    public DestSubClass(){

    }

    public DestSubClass(String dsonId, String sonName) {
        this.dsonId = dsonId;
        this.sonName = sonName;
    }
}

(4)Source

@Getter
@Setter
public class Source {
    private String id;
    private String name;
    private Integer age;
    private SouSubClass sourceSon;
    private List<SouSubClass> listSon;
    private Map<Integer, SouSubClass> mapSon;
    private Date createTime;

    public Source() {

    }

    public Source(String id, String name) {
        this.id = id;
        this.name = name;
    }

    public Source(String id, String name, Integer age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }
}

(5)Destination

@Getter
@Setter
public class Destination {
    private Long id;
    private String name;
    private Integer age;
    private DestSubClass destinationSon;
    private List<DestSubClass> sonList;
    private Map<Integer, DestSubClass> sonMap;
    private String excessParam;
    private Date createTime;

    public Destination() {

    }

    public Destination(Long id, String name) {
        this.id = id;
        this.name = name;
    }
}

ModelMapper 配置类

/**
 * 描述:ModelMapper 配置
 */
@Configuration
public class ModelMapperConfig {

    @Bean
    @Scope("singleton")
    public ModelMapper getModelMapper() {
        ModelMapper modelMapper = new ModelMapper();
        //默认为standard模式,设置为strict模式
        modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);

        // 类型映射代码
        sourceSonToDestinationSon(modelMapper);
        sourceToDestination(modelMapper);

        //验证映射
        modelMapper.validate();

        // 配置代码
        return modelMapper;
    }

    /**
     * 描述:声明 Source 类转 Destination 类的 Mapper
     * @param modelMapper
     * @Date  2019/05/09
     */
    private void sourceSonToDestinationSon(ModelMapper modelMapper) {
        modelMapper.createTypeMap(SouSubClass.class, DestSubClass.class)
                .addMapping(SouSubClass::getSonId, DestSubClass::setDsonId)
                .addMapping(SouSubClass::getSonName, DestSubClass::setSonName)
                .addMappings(mapper -> mapper.skip(DestSubClass::setExcessParam));
    }

    private void sourceToDestination(ModelMapper modelMapper) {
        modelMapper.createTypeMap(Source.class, Destination.class)
                .addMappings(mapper -> mapper.using((Converter<Integer, Integer>) context -> {
                        if (context.getSource() == null) {
                            return 18;
                        }
                        return context.getSource();
                    }).map(Source::getAge, Destination::setAge))
                .addMappings(mapper -> mapper.using((Converter<Date, Date>) context -> {
                        if (context.getSource() == null) {
                            return new Date();
                        }
                        return context.getSource();
                    }).map(Source::getCreateTime, Destination::setCreateTime))
                .addMapping(Source::getSourceSon, Destination::setDestinationSon)
                .addMapping(Source::getListSon, Destination::setSonList)
                .addMapping(Source::getMapSon, Destination::setSonMap)
                .addMappings(mapper -> mapper.skip(Destination::setExcessParam));
    }
}

ModelMapper Service 类

public interface TestService {

    Destination testSourceToDestination(Source source);

    List<Destination> testSourceToDestinationList(List<Source> sources);
}
@Service
public class TestServiceImpl implements TestService {

    @Autowired
    private ModelMapper modelMapper;

    @Override
    public Destination testSourceToDestination(Source source) {
        Destination destination = modelMapper.map(source, Destination.class);

        return destination;  // a 处
    }

    @Override
    public List<Destination> testSourceToDestinationList(List<Source> sources) {
        Type type = new TypeToken<List<Destination>>(){}.getType();
        List<Destination> destinations = modelMapper.map(sources, type);

        return destinations; // b 处
    }
}

测试类

@RunWith(SpringRunner.class)
@SpringBootTest(classes = TestApplication.class)
public class TestServiceImplTest {

    @Autowired
    private TestService testService;

    private static Source source1 = new Source("a", "发生的", 24);
    private static Source source2 = new Source("b", "发生的");

    private static List<Source> sources = new ArrayList<>();

    static {
        List<BaseClass> baseClasses1 = new ArrayList<>();
        baseClasses1.add(new BaseClass("aa", "发生的111"));
        baseClasses1.add(new BaseClass("bb", "发生的222"));
        SouSubClass subClass1 = new SouSubClass("aaa", "发生的3333");
        subClass1.setGrandSons(baseClasses1);

        List<BaseClass> baseClasses2 = new ArrayList<>();
        baseClasses2.add(new BaseClass("cc", "国防观"));
        baseClasses2.add(new BaseClass("dd", "国防观"));
        SouSubClass subClass2 = new SouSubClass("ccc", "规范的大哥");
        subClass2.setGrandSons(baseClasses2);

        List<SouSubClass> sourceSonList = new ArrayList<>();
        sourceSonList.add(subClass1);
        sourceSonList.add(subClass2);

        Map<Integer, SouSubClass> sourceSonMap = new HashMap<>();
        sourceSonMap.put(1, subClass1);
        sourceSonMap.put(2, subClass2);

        source1.setCreateTime(new Date(System.currentTimeMillis()-98978609));
        source1.setSourceSon(subClass1);
        source1.setListSon(sourceSonList);
        source1.setMapSon(sourceSonMap);

        source2.setSourceSon(subClass1);
        source2.setListSon(sourceSonList);
        source2.setMapSon(sourceSonMap);

        sources.add(source1);
        sources.add(source2);
    }

    @Test
    public void testSourceToDestination() {
        testService.testSourceToDestination(source1);
        testService.testSourceToDestination(source2);
    }

    @Test
    public void testSourceToDestinationList() {
        testService.testSourceToDestinationList(sources);
    }
}

测试结果

在 ab 两处打上断点,查看变量转换前后的值,证实转换成功。

到此这篇关于Java中ModelMapper 的高级使用的文章就介绍到这了,更多相关Java ModelMapper内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 通过url方式传递中文乱码的解决方法

    通过url方式传递中文乱码的解决方法

    本篇文章主要是对通过url方式传递中文乱码的解决方法进行了介绍,需要的朋友可以过来参考下,希望对大家有所帮助
    2013-12-12
  • springboot使用Mybatis(xml和注解)过程全解析

    springboot使用Mybatis(xml和注解)过程全解析

    这篇文章主要介绍了springboot使用Mybatis(xml和注解)过程全解析 ,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-05-05
  • Java知识点归纳 —给Java新手的一些建议(新手必看)

    Java知识点归纳 —给Java新手的一些建议(新手必看)

    以下简单介绍了下我对于这些java基本知识点和技术点的一些看法和心得,这些内容都源自于我这些年来使用java的一些总结
    2016-05-05
  • Java 调用天气Webservice详解及实例代码

    Java 调用天气Webservice详解及实例代码

    这篇文章主要介绍了Java 调用天气Webservice详解及实例代码的相关资料,这里附实例代码,使用java 调用webservice 的小应用,需要的朋友可以参考下
    2016-11-11
  • SpringBoot 分布式验证码登录方案示例详解

    SpringBoot 分布式验证码登录方案示例详解

    为了防止验证系统被暴力破解,很多系统都增加了验证码效验,比较常见的就是图片二维码,业内比较安全的是短信验证码,当然还有一些拼图验证码,加入人工智能的二维码等等,我们今天的主题就是前后端分离的图片二维码登录方案,感兴趣的朋友一起看看吧
    2023-10-10
  • Java如何获取一个随机数 Java猜数字小游戏

    Java如何获取一个随机数 Java猜数字小游戏

    这篇文章主要为大家详细介绍了Java如何获取一个随机数,类似猜数字小游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-03-03
  • SpringBoot开发项目,引入JPA找不到findOne方法的解决

    SpringBoot开发项目,引入JPA找不到findOne方法的解决

    这篇文章主要介绍了SpringBoot开发项目,引入JPA找不到findOne方法的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-11-11
  • 全面详解Maven打包及其相关插件和高级特性

    全面详解Maven打包及其相关插件和高级特性

    这篇文章主要为大家介绍了Maven打包及其相关插件和高级特性的全面详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-05-05
  • Maven依赖冲突原因以及解决方法

    Maven依赖冲突原因以及解决方法

    依赖冲突是指项目依赖的某一个 jar 包,有多个不同的版本,因而造成类包版本冲突依赖冲突很经常是类包之间的间接依赖引起的,本文将给大家介绍Maven依赖冲突原因以及解决方法,需要的朋友可以参考下
    2023-12-12
  • java构造函数示例(构造方法)

    java构造函数示例(构造方法)

    这篇文章主要介绍了java构造函数示例(构造方法),需要的朋友可以参考下
    2014-03-03

最新评论