首页 > 编程语言 >Java对象转换工具-orika

Java对象转换工具-orika

时间:2022-12-26 14:56:10浏览次数:38  
标签:orika Java aType param bType import class 转换

1.概述

Orika是java Bean映射框架,可以实现从一个对象递归拷贝数据至另一个对象,它使用字节码生成器创建开销最小的快速映射,比其他基于反射方式实现更快。对于名称不相同或类型不一样,则需要单独映射。

2.实战演练

2.1环境准备

新建一个SpringBoot的项目,导入需要的依赖

<dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
</dependency>
 <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
</dependency>

2.2引入orika

1)导入依赖

<dependency>
     <groupId>ma.glasnost.orika</groupId>
     <artifactId>orika-core</artifactId>
     <version>1.5.1</version>
</dependency>

2)创建对象UserDto,作为源对象

package com.zxh.test;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserDto {
    private String id;
    private String name;
    private Integer age;
}

3)创建对象UserVo,作为目标对象

package com.zxh.test;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserVo {
    private String id;
    private String name;
    private Integer userAge;
}

4)编写容器注入类,避免重复创建映射工厂类

package com.zxh.test.config;

import ma.glasnost.orika.MapperFactory;
import ma.glasnost.orika.impl.DefaultMapperFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MapperFacotoryAutoWire {

    @Bean
    public MapperFactory getFactory(){
        return new DefaultMapperFactory.Builder().build();
    }

}

2.3与dozer的比较

由于后面章节会对其方法进行封装,故这里直接与dozer进行对比

    //注入
    @Resource
    private ma.glasnost.orika.MapperFactory mapperFactory;

    @Test
    public void test() {
        Integer t = 1000000;
        List<UserDto> list = new ArrayList<>();
        for (int i = 0; i < t; i++) {
            UserDto userDto = new UserDto("10" + i, "男", 20);
            list.add(userDto);
        }
        StopWatch watch = new StopWatch();
        watch.start("orika");
        // 因为存在字段不一样,需要手动映射一下。如果所有字段一样,则不用写mapperFactory.classMap()方法
        mapperFactory.classMap(UserDto.class, UserVo.class)
                .field("age", "userAge")//不一样的字段映射,源字段->目标字段
                .byDefault()
                .register();
        list.stream().forEach(item -> {
            UserVo userVo = mapperFactory.getMapperFacade().map(item, UserVo.class);
        });
        watch.stop();
        System.out.println("orika复制用时:" + watch.getLastTaskTimeMillis());
        watch.start("dozer");
        list.stream().forEach(item -> {
            UserVo userVo = mapper.map(item, UserVo.class);
        });
        watch.stop();
        System.out.println("dozer复制用时:" + watch.getLastTaskTimeMillis());
    }

打印的结果如下:

在上述的案例中,为了性能的比较,故分别进行100万次的对象复制,可以很明显的看出两者的性能差异,显而易见,orika的性能优于dozer。

那么orika有没有对集合的快速复制呢?答案是有,下面使用普通的foreach和其自带的集合复制进行对比:

    @Test
    public void test9() {
        Integer t = 100000;
        List<UserDto> list = new ArrayList<>();
        for (int i = 0; i < t; i++) {
            UserDto userDto = new UserDto("10" + i, "男", 20);
            list.add(userDto);
        }
        StopWatch watch = new StopWatch();
        // 因为存在字段不一样,需要手动映射一下。如果所有字段一样,则不用写mapperFactory.classMap()方法
        mapperFactory.classMap(UserDto.class, UserVo.class)
                .field("age", "userAge")//不一样的字段映射,源字段->目标字段
                .byDefault()
                .register();

        watch.start("orika1");
        list.stream().forEach(item -> {
            UserVo userVo = mapperFactory.getMapperFacade().map(item, UserVo.class);
        });
        watch.stop();
        System.out.println("orika-map复制用时:" + watch.getLastTaskTimeMillis());
        watch.start("orika2");
        List<UserVo> userVos = mapperFactory.getMapperFacade().mapAsList(list, UserVo.class);
        watch.stop();
        System.out.println("orika-list复制用时:" + watch.getLastTaskTimeMillis());
    }

打印的结果如下:

虽然只进行了10万次的复制,但性能就显现出来了。

3.封装使用

package com.zxh.test.util;

import ma.glasnost.orika.MapperFactory;
import ma.glasnost.orika.metadata.ClassMapBuilder;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @author zhongyushi
 */
@Component
public class OrikaUtil {
    @Resource
    private MapperFactory mapperFactory;

    /**
     * 字段映射
     *
     * @param aType  源对象类型
     * @param bType  目标对象类型
     * @param fields 不同字段映射值
     * @param <A>
     * @param <B>
     */
    private <A, B> void filedMap(Class<A> aType, Class<B> bType, Map<String, String> fields) {
        ClassMapBuilder<A, B> mapBuilder = mapperFactory.classMap(aType, bType);
        if (fields != null && fields.size() > 0) {
            Set<Map.Entry<String, String>> entries = fields.entrySet();
            for (Map.Entry<String, String> entry : entries) {
                mapBuilder.field(entry.getKey(), entry.getValue());
            }
        }
        mapBuilder.byDefault().register();
    }

    /**
     * 对象的复制
     *
     * @param aType  源对象类型
     * @param bType  目标对象类型
     * @param fields 不同字段映射值
     * @param source 要复制的对象
     * @param <A>
     * @param <B>
     * @return
     */
    public <A, B> B beanCopy(Class<A> aType, Class<B> bType, Map<String, String> fields, A source) {
        filedMap(aType, bType, fields);
        B target = mapperFactory.getMapperFacade().map(source, bType);
        return target;
    }

    /**
     * 对象的复制
     *
     * @param aType  源对象类型
     * @param bType  目标对象类型
     * @param source 要复制的对象
     * @param <A>
     * @param <B>
     * @return
     */
    public <A, B> B beanCopy(Class<A> aType, Class<B> bType, A source) {
        return beanCopy(aType, bType, null, source);
    }

    /**
     * 集合的复制
     *
     * @param aType  源对象类型
     * @param bType  目标对象类型
     * @param fields 不同字段映射值
     * @param source 要复制的对象
     * @param <A>
     * @param <B>
     * @return
     */
    public <A, B> List<B> beanListCopy(Class<A> aType, Class<B> bType, Map<String, String> fields, Iterable<A> source) {
        filedMap(aType, bType, fields);
        List<B> bList = mapperFactory.getMapperFacade().mapAsList(source, bType);
        return bList;
    }

    /**
     * 集合的复制
     *
     * @param aType  源对象类型
     * @param bType  目标对象类型
     * @param source 要复制的对象
     * @param <A>
     * @param <B>
     * @return
     */
    public <A, B> List<B> beanListCopy(Class<A> aType, Class<B> bType, Iterable<A> source) {
        return beanListCopy(aType, bType, null, source);
    }
}

对其方法进行进一步的封装,在使用的地方注入使用:

    @Autowired
    private OrikaUtil orikaUtil;

    @Test
    public void test0() {
        UserDto userDto = new UserDto("10", "男", 20);
        Map<String, String> map = new HashMap<>();
        map.put("age", "userAge");
        UserVo userVo = orikaUtil.beanCopy(UserDto.class, UserVo.class, map, userDto);
        System.out.println(userVo);
    }

    @Test
    public void test1() {
        Integer t = 10;
        List<UserDto> list = new ArrayList<>();
        for (int i = 0; i < t; i++) {
            UserDto userDto = new UserDto("10" + i, "男", 20);
            list.add(userDto);
        }
        Map<String, String> map = new HashMap<>();
        map.put("age", "userAge");
        System.out.println(orikaUtil.beanListCopy(UserDto.class, UserVo.class, map, list));
    }

使用起来也格外的方便。

标签:orika,Java,aType,param,bType,import,class,转换
From: https://www.cnblogs.com/zys2019/p/17005798.html

相关文章

  • 在java中操作redis
    Redis的客户端很多,官方推荐三种:(Jedis,lettuce,Redission)。springdataredis,在SpringBoot项目中还提供了对应的Starter,即Spring-boot-starter-data-redis.Jedis的maven......
  • 【Java】无法将java.util.LinkedHashMap强制转换为X
    JsonJack:无法将java.util.LinkedHashMap强制转换为X1.概述Jackson是一个广泛使用的Java库,它使可以方便地对JSON或XML进行序列化/反序列化。有时,当尝试将JSON或XML反序列......
  • 29_Java中的Stream流
    Java中的Stream流总的来所就是将一组数据转换为流进行操作过滤,然后再将其还原进行操作一、体验Stream流需求:按照下面的要求完成集合的创建和遍历​ 创建......
  • 为什么阿里的Java开发规范中禁止使用Executors创建线程池?
    一.问题概述最近壹哥有个学生出去面试,面试官的一个问题是:在开发中你使用什么方式创建线程池?这个学生答曰:使用jdk中自带的工厂类Executors创建线程池!该学生回答完问题后,感......
  • 高薪程序员&Java面试题精讲系列汇总
    因为没有分类归纳博客的功能,所以特写本帖汇总《高薪程序员面试题精讲系列教程》,方便大家查阅!希望各位小伙伴,可以从我的拙作中能对Java的高频面试题有所掌握,也希望各位可以多......
  • Linux系统上Java单体项目崩溃自启动脚本(通用型)
    本文转自https://blog.csdn.net/qq_38374397/article/details/127566529实现对进程的监控这里只需要三步:设置服务启动脚本设置监控shell脚本设置linux周期定时执行指令......
  • Java代码打包
    Java代码打包一:IDEA工具1、右侧的maven直接clean后package2、终端命令mvncleanpackage3、项目结构,创建工件,选择清单属性,构建工件4、指定主类打包、含多个类的jar打......
  • socket 大端 小端 转换《一》
    不同机器内部对变量的字节存储顺序不同,有的采用大端模式(big-endian),有的采用小端模式(little-endian)。大端模式是指高字节数据存放在低地址处,低字节数据放在高地址处。小......
  • Java基础之常用类(String类)
    String类定义String类代表字符串。Java程序中的所有字符串字面值(如"abc")都作为此类的实例实现。我们可以将字符串看作是String,但是严格意义上来说,String还是......
  • socket 大端 小端 转换《二》
    (1)对于位域结构中的变量来说,其长度不能跨越字节,也就是说不能超过8位。当然如果设置空白位(无名变量,仅仅用作占位的)是没有这个限制的。如果一个字节剩下的位长度不够一个位域,......