Orika应用示例 - Java 代码版

Orika是一个简单、快速的JavaBean拷贝框架,它能够递归地将数据从一个JavaBean复制到另一个JavaBean。

Orika底层采用了javassist类库生成Bean映射的字节码,因此效率要远高于通过反射来实现的BeanUtils.copyProperties()。
官方地址:http://orika-mapper.github.io/orika-docs/

  • maven依赖:
        <dependency>
            <groupId>ma.glasnost.orika</groupId>
            <artifactId>orika-core</artifactId>
            <version>1.5.4</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <scope>compile</scope>
            <version>1.18.16</version>
        </dependency>

        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>30.1-jre</version>
        </dependency>
  • 测试的实体对象:
import lombok.Data;
import lombok.experimental.Accessors;


@Data
@Accessors(chain = true)
public class Role {
    private Integer id;
    private String name;
}



import lombok.Data;
import lombok.experimental.Accessors;

import java.util.List;

@Data
@Accessors(chain = true)
public class User {
    private String id;
    private String name;
    private Integer age;
    List<User> userList;
    List<Role> roles;
}


import lombok.Data;
import lombok.experimental.Accessors;

import java.util.List;

@Data
@Accessors(chain = true)
public class UserDto {
    private String id;
    private String name;
    private String userName;
    private Integer age;
    List<User> userList;
    List<Role> roleList;
}

  • 封装的Orika工具类:
/**
 * 基于Orika的属性映射工具类 - Orika是一个简单、快速的JavaBean拷贝框架,它能够递归地将数据从一个JavaBean复制到另一个JavaBean,Orika底层采用了javassist类库生成Bean映射的字节码
 * <p>
 * 1. 支持模糊类型映射(如:Integer <-> Long, Integer <-> String)
 * 2. 支持对象中的list映射
 * <p>
 * 性能:手动拷贝 > cglib beanCopier > orika mapper > spring beanUtils > apache commons beanUtils
 *
 */
public class OrikaMapperUtils {

    /**
     * 默认字段工厂
     */
    private static final MapperFactory MAPPER_FACTORY = new DefaultMapperFactory.Builder().build();

    /**
     * 默认字段实例
     */
    private static final MapperFacade MAPPER_FACADE = MAPPER_FACTORY.getMapperFacade();

    /**
     * 实例缓存
     */
    private final static Cache<Object, Object> CACHE_MAPPER_FACADE_MAP = CacheBuilder.newBuilder().maximumSize(100)
            .concurrencyLevel(10)
            .expireAfterWrite(60L, TimeUnit.SECONDS)
            .recordStats()
            .build();

    /**
     * 映射实体(默认字段)
     *
     * @param data    源数据(对象)
     * @param toClass 映射类对象
     * @return 映射类对象
     */
    public static <E, T> E map(T data, Class<E> toClass) {
        return MAPPER_FACADE.map(data, toClass);
    }

    /**
     * 映射实体(自定义配置)
     *
     * @param data      源数据(对象)
     * @param toClass   映射类对象
     * @param configMap 自定义配置
     *                  - 用于处理源对象与目标对象字段名不匹配的情况 - 格式:{key=源对象中的字段名 : value=目标对象中的字段名}
     * @return 映射类对象
     */
    public static <E, T> E map(T data, Class<E> toClass, Map<String, String> configMap) {
        MapperFacade mapperFacade = getMapperFacade(toClass, data.getClass(), configMap);
        return mapperFacade.map(data, toClass);
    }

    /**
     * 映射集合(默认字段)
     *
     * @param data    源数据(集合)
     * @param toClass 映射类对象
     * @return 映射类对象(集合)
     */
    public static <E, T> List<E> mapAsList(Collection<T> data, Class<E> toClass) {
        if (Objects.isNull(data)) {
            return Collections.emptyList();
        } else {
            return MAPPER_FACADE.mapAsList(data, toClass);
        }
    }


    /**
     * 映射集合(自定义配置)
     *
     * @param data      源数据(集合)
     * @param toClass   映射类
     * @param configMap 自定义配置
     *                  - 用于处理源对象与目标对象字段名不匹配的情况 - 格式:{key=源对象中的字段名 : value=目标对象中的字段名}
     * @return 映射类对象(集合)
     */
    public static <E, T> List<E> mapAsList(Collection<T> data, Class<E> toClass, Map<String, String> configMap) {
        if (Objects.isNull(data)) {
            return Collections.emptyList();
        }
        Optional<T> first = data.stream().findFirst();
        if (first.isPresent()) {
            MapperFacade mapperFacade = getMapperFacade(toClass, first.get().getClass(), configMap);
            return mapperFacade.mapAsList(data, toClass);
        } else {
            return Collections.emptyList();
        }
    }

    /**
     * 获取自定义映射
     *
     * @param toClass   映射类
     * @param dataClass 数据映射类
     * @param configMap 自定义配置
     * @return 映射类对象
     */
    private static <E, T> MapperFacade getMapperFacade(Class<E> toClass, Class<T> dataClass, Map<String, String> configMap) {
        String mapKey = dataClass.getCanonicalName() + "_" + toClass.getCanonicalName();
        Object o = CACHE_MAPPER_FACADE_MAP.getIfPresent(mapKey);
        MapperFacade mapperFacade;
        if (Objects.isNull(o)) {
            MapperFactory factory = new DefaultMapperFactory.Builder().build();
            ClassMapBuilder classMapBuilder = factory.classMap(dataClass, toClass);
            configMap.forEach(classMapBuilder::field);
            classMapBuilder.byDefault().register();
            mapperFacade = factory.getMapperFacade();
            CACHE_MAPPER_FACADE_MAP.put(mapKey, mapperFacade);
        } else {
            mapperFacade = (MapperFacade) o;
        }
        return mapperFacade;
    }

}
  •  测试类
import java.util.*;


public class OrikaMapperTest {
    public static void main(String[] args) {
        User userA = new User().setId("111").setName("张三").setAge(20);
        userA.setUserList(Arrays.asList(new User[]{new User().setId("121").setName("张三1").setAge(21), new User().setId("122").setName("张三2").setAge(22)}));
        userA.setRoles(Arrays.asList(new Role[]{new Role().setId(1).setName("老师"), new Role().setId(2).setName("班主任")}));
        Map<String, String> map = new HashMap<String, String>() {
            {
                put("roles", "roleList");
            }
        };
        UserDto userDto = OrikaMapperUtils.map(userA, UserDto.class, map);
        System.out.println("无configMap的对象映射(源):" + userA);
        System.out.println("无configMap的对象映射(目标):" + userDto);

        Map<String, String> configMap = new HashMap<String, String>() {
            {
                put("name", "userName");
            }
        };
        UserDto userDto2 = OrikaMapperUtils.map(userA, UserDto.class, configMap);
        System.out.println("带configMap的对象映射(源):" + userA);
        System.out.println("带configMap的对象映射(目标):" + userDto2);
        //A对象
        List<User> listA = Arrays.asList(new User().setId("123").setName("张三").setAge(20));
        List<UserDto> userDtos = OrikaMapperUtils.mapAsList(listA, UserDto.class);
        System.out.println("无configMap的list映射(源):" + listA);
        System.out.println("无configMap的list映射(目标):" + userDtos);
        List<UserDto> userDtos2 = OrikaMapperUtils.mapAsList(listA, UserDto.class, configMap);
        System.out.println("带configMap的list映射(源):" + listA);
        System.out.println("带configMap的list映射(目标):" + userDtos2);
    }
}
  • 输出结果: 
  1. 无configMap的对象映射(源):User(id=111, name=张三, age=20, userList=[User(id=121, name=张三1, age=21, userList=null, roles=null), User(id=122, name=张三2, age=22, userList=null, roles=null)], roles=[Role(id=1, name=老师), Role(id=2, name=班主任)])
  2. 无configMap的对象映射(目标):UserDto(id=111, name=张三, userName=null, age=20, userList=[User(id=121, name=张三1, age=21, userList=null, roles=null), User(id=122, name=张三2, age=22, userList=null, roles=null)], roleList=[Role(id=1, name=老师), Role(id=2, name=班主任)])
  3. 带configMap的对象映射(源):User(id=111, name=张三, age=20, userList=[User(id=121, name=张三1, age=21, userList=null, roles=null), User(id=122, name=张三2, age=22, userList=null, roles=null)], roles=[Role(id=1, name=老师), Role(id=2, name=班主任)])
  4. 带configMap的对象映射(目标):UserDto(id=111, name=张三, userName=null, age=20, userList=[User(id=121, name=张三1, age=21, userList=null, roles=null), User(id=122, name=张三2, age=22, userList=null, roles=null)], roleList=[Role(id=1, name=老师), Role(id=2, name=班主任)])
  5. 无configMap的list映射(源):[User(id=123, name=张三, age=20, userList=null, roles=null)]
  6. 无configMap的list映射(目标):[UserDto(id=123, name=张三, userName=null, age=20, userList=null, roleList=null)]
  7. 带configMap的list映射(源):[User(id=123, name=张三, age=20, userList=null, roles=null)]
  8. 带configMap的list映射(目标):[UserDto(id=123, name=张三, userName=null, age=20, userList=null, roleList=null)]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值