吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1333|回复: 20
收起左侧

[Java 原创] Java开发中超好用Orika属性映射工具

[复制链接]
mabin 发表于 2024-3-14 09:43
本帖最后由 mabin 于 2024-3-14 17:39 编辑

Orika属性映射工具

引入pom依赖

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

上干货

封装的工具类:OriUtils

import ma.glasnost.orika.MapperFacade;
import ma.glasnost.orika.MapperFactory;
import ma.glasnost.orika.impl.DefaultMapperFactory;
import ma.glasnost.orika.metadata.ClassMapBuilder;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Description: Orika封装的工具类
 * @date 2021/7/2 16:16
 * @AuThor mb
 */

public class OrikaUtils {

    private static final MapperFactory FACTORY = new DefaultMapperFactory.Builder().build();
    /**
     * 缓存实例集合
     */
    private static Map<String, MapperFacade> cacheMapper = new ConcurrentHashMap<>();

    private MapperFacade mapper;

    public OrikaUtils(MapperFacade mapper) {
        this.mapper = mapper;
    }

    /**
     * 转换实体函数
     *
     * @Param sourceEntity 源实体
     * @param targetClass  目标类对象
     * @param refMap       配置源类与目标类不同字段名映射
     * @param <S>          源泛型
     * @param <T>          目标泛型
     * @Return 目标实体
     */
    public static <S, T> T convert(S sourceEntity, Class<T> targetClass, Map<String, String> refMap) {
        if (sourceEntity == null) {
            return null;
        }
        return classMap(sourceEntity.getClass(), targetClass, refMap).map(sourceEntity, targetClass);
    }

    /**
     * 转换实体函数
     *
     * @param sourceEntity 源实体
     * @param targetClass  目标类对象
     * @param <S>          源泛型
     * @param <T>          目标泛型
     * @return 目标实体
     */
    public static <S, T> T convert(S sourceEntity, Class<T> targetClass) {
        return convert(sourceEntity, targetClass, null);
    }

    /**
     * 转换实体集合函数
     *
     * @param sourceEntityList 源实体集合
     * @param targetClass      目标类对象
     * @param refMap           配置源类与目标类不同字段名映射
     * @param <S>              源泛型
     * @param <T>              目标泛型
     * @return 目标实体集合
     */
    public static <S, T> List<T> convertList(List<S> sourceEntityList, Class<T> targetClass, Map<String, String> refMap) {
        if (sourceEntityList == null) {
            return null;
        }
        if (sourceEntityList.size() == 0) {
            return new ArrayList<>(0);
        }
        return classMap(sourceEntityList.get(0).getClass(), targetClass, refMap).mapAsList(sourceEntityList, targetClass);
    }

    /**
     * 转换实体集合函数
     *
     * @param sourceEntityList 源实体集合
     * @param targetClass      目标类对象
     * @param <S>              源泛型
     * @param <T>              目标泛型
     * @return 目标实体集合
     */
    public static <S, T> List<T> convertList(List<S> sourceEntityList, Class<T> targetClass) {
        return convertList(sourceEntityList, targetClass, null);
    }

    /**
     * @param source
     * @param target
     * @param <V>
     * @param <P>
     * @return
     */
    public static <V, P> OrikaUtils classMap(Class<V> source, Class<P> target) {
        return classMap(source, target, null);
    }

    /**
     * 属性名称一致可用
     *
     * @param source
     * @param target
     * @param <V>
     * @param <P>
     * @return
     */
    public static synchronized <V, P> OrikaUtils classMap(Class<V> source, Class<P> target, Map<String, String> refMap) {
        String key = source.getCanonicalName() + ":" + target.getCanonicalName();
        if (cacheMapper.containsKey(key)) {
            return new OrikaUtils(cacheMapper.get(key));
        }
        if (CollectionUtils.isEmpty(refMap)) {
            FACTORY.classMap(source, target).byDefault().register();
        } else {
            ClassMapBuilder<V, P> classMapBuilder = FACTORY.classMap(source, target);
            refMap.forEach(classMapBuilder::field);
            classMapBuilder.byDefault().register();
        }
        MapperFacade mapperFacade = FACTORY.getMapperFacade();
        cacheMapper.put(key, mapperFacade);

        return new OrikaUtils(mapperFacade);
    }

    /**
     * 复制对象
     *
     * @param source
     * @param target
     * @param <V>
     * @param <P>
     * @return
     */
    public <V, P> P map(V source, Class<P> target) {
        return mapper.map(source, target);
    }

    /**
     * 复制List
     *
     * @param source
     * @param target
     * @param <V>
     * @param <P>
     * @return
     */
    public <V, P> List<P> mapAsList(List<V> source, Class<P> target) {
        return CollectionUtils.isEmpty(source) ? Collections.emptyList() : mapper.mapAsList(source, target);
    }

}

演示示例:

  • 单个对象属性映射
  • List集合属性映射
        // 单个对象属性映射
        Map<String, String> refMap = new HashMap<>(2);
                // 属性名的对应关系(属性名不一致的情况下使用)
        refMap.put("postId", "blogId");
        Comment com = OrikaUtils.convert(comment, Comment.class, refMap);

    @Override
    public List<ResponseSimpleTopic> queryTopicList(Integer desc) {
        if (desc.equals(1)) {
            return baseMapper.queryTopicList();
        }
        LambdaQueryWrapper<Topic> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select(Topic::getId, Topic::getTopicName);
        List<Topic> topics = this.list(queryWrapper);
        // List集合属性映射
        return OrikaUtils.classMap(Topic.class, ResponseSimpleTopic.class)
                .mapAsList(topics, ResponseSimpleTopic.class);
    }

免费评分

参与人数 2吾爱币 +2 热心值 +1 收起 理由
shuocai + 1 + 1 用心讨论,共获提升!
jh52pj + 1 用心讨论,共获提升!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

Naylor 发表于 2024-11-21 11:33
java  bean 的拷贝问题,之前还真研究过,写了一个博客,感兴趣的可以看看:https://developer.aliyun.com/article/1403855?spm=a2c6h.24874632.expert-profile.112.2c9834e4HCseiV

大多数开发场景来说 ,BeanCopier + 缓存  , 是最优解, 为六边形解决方案。
 楼主| mabin 发表于 2024-3-14 17:12
a928418 发表于 2024-3-14 16:45
这个和原生的BeanUtils有什么区别!?

apache和spring的BeanUtils工具,都是基于反射特性进行的,大数据量时,性能堪忧,而且都是浅拷贝的

这个orika带有自定义转换器,不同名属性也可拷贝,而且是深拷贝,性能也更优
xiaoyi151 发表于 2024-3-14 13:10
houzhanwu 发表于 2024-3-14 13:10
直接   Mapstruct  走起
code2t 发表于 2024-3-14 13:21
这个框架支持深拷贝吗?
 楼主| mabin 发表于 2024-3-14 15:36
houzhanwu 发表于 2024-3-14 13:10
直接   Mapstruct  走起

相比 Mapstruct 的话,减少了各种Mapper实例的配置,但是性能方面,还是 Mapstruct 最顶
 楼主| mabin 发表于 2024-3-14 16:26
Lidaigua229 发表于 2024-3-14 16:14
也就是简化了部分操作,但牺牲了一定的性能

一定程度上是这样的
icookie1314 发表于 2024-3-14 17:15
这个工具类不错  
starryskyhello 发表于 2024-3-16 09:48
可以,挺不错。
sihehe 发表于 2024-3-28 16:55
学到了,去研究研究,看看底层原理是啥
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-24 09:44

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表