BeanDtoVoUtil 工具类( v-1.0.1 版本) , 原来不管是实体类对象T 还是List<T> 还是Page<T> 的Entity、Dto、Vo的相互转换还能怎么简单,V2版本

本文基于 原来不管是实体类对象T 还是List 还是Page 的Entity、Dto、Vo的相互转换还能怎么简单 改进并优化

一、Entity、Dto、Vo 转换方式一览

方法 描叙 推荐级别(0-5)
1、set/get 原始使用方法 2 (看业务)
2、cglib 运行时动态生成 set/get ,需避免频繁create,大数据量性能最佳, 5 (推荐使用)
3、mapstruct 编译时生成的set/get, 提供字段映射,类型转换功能, 大数据量性能佳,略逊与cglib, 不过很接近, 功能比cglib 强 5 (推荐使用)
4、springframework下的 BeanUtils 的 copyProperties spring 下提供的拷贝,使用反射拷贝,性能尚佳, 大量数据下不太理想 3 (允许使用)
5、apache 下的 BeanUtils 的 copyProperties apache 提供的拷贝,使用反射拷贝, 性能差 0 (强制禁用)
6、apache 下的 PropertyUtils.copyProperties apache 提供的拷贝,使用反射拷贝,性能差 0 (强制禁用)

二、使用cglib 转换工具类

package com.ws.ldy.common.utils;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import net.sf.cglib.beans.BeanCopier;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 *  Dto,Vo,entity 转换工具类
 *
 *  @param1 oldClass 原数据--Dto,Vo,entity
 *  @param1 newClass 转换为--Dto,Vo,entity
 * @author wangsong
 * @mail [email protected]
 * @date 2020/11/20 0020 16:22
 * @version 1.0.1 (与版本0.0.7更新)
 */
public class BeanDtoVoUtil<V, E> {
    
    

    /**
     * BeanCopier的缓存
     */
    static final ConcurrentHashMap<String, BeanCopier> BEAN_COPIER_CACHE = new ConcurrentHashMap<>();

    /**
     * dot ,do ,entity 相互转换(使用cglib)
     * <P>
     *  1、使用 cglib, 几乎无性能损耗, 和 mapstruct 和 get/set 性能不相上下,甚至更快
     *   ---- mapstruct 在 编译时生成class文件的set,get方法,功能更全,支持属性key不一致,属性类型不一致的配置替换
     *   ---- cglib 在 BeanCopier.create动态生成set/get方法,功能单一,但性能可观,注意避免频繁 BeanCopier.create, 会重复动态生成get/set,将达不到预期的性能效果
     *
     *  2、使用 springboot的
     *   ---- BeanUtils.copyProperties(oldClass, newInstance);
     *
     *  3、使用 mapstruct
     *   ---- 参考 AdminAuthorityConverter 转换类,启动项目会动态生成 AdminAuthorityConverterImpl的calss类,并生成转换方法
     * </P>
     *
     * @param oldClass 原数据--Dto,Vo,entity
     * @param newClass 转换为--Dto,Vo,entity
     * @return
     */
    public static <E> E convert(Object oldClass, Class<E> newClass) {
    
    
        if (oldClass == null) {
    
    
            return null;
        }
        if (newClass == null) {
    
    
            return null;
        }
        E newInstance = null;
        try {
    
    
            newInstance = newClass.newInstance();
        } catch (Exception e) {
    
    
            e.printStackTrace();
            return null;
        }
        String key = oldClass.getClass().getName() + ":" + newClass.getName();
        BeanCopier copier = null;
        if (BEAN_COPIER_CACHE.containsKey(key)) {
    
    
            copier = BEAN_COPIER_CACHE.get(key);
        } else {
    
    
            copier = BeanCopier.create(oldClass.getClass(), newInstance.getClass(), false);
            BEAN_COPIER_CACHE.put(key, copier);
        }
        copier.copy(oldClass, newInstance, null);
        return newInstance;
    }


    /**
     * Page<Entity> 分页对象转 Page<Vo> 
     *
     * @param page
     * @param v
     * @return com.baomidou.mybatisplus.core.metadata.IPage<V>
     * @author ws
     * @mail [email protected]
     * @date 2020/4/23 0023 11:26
     */
    public static <T, V> IPage<V> pageVo(Page<T> page, Class<V> v) {
    
    
        if (page == null) {
    
    
            return null;
        }
        return page.convert(item -> BeanDtoVoUtil.convert(item, v));
    }


    /**
     * list<Entity> 集合对象转list<Vo> ( list 循环)
     *
     * @param oldList
     * @param v
     * @return com.baomidou.mybatisplus.core.metadata.IPage<V>
     * @author ws
     * @mail [email protected]
     * @date 2020/4/23 0023 11:26
     */
    public static <T, V> List<V> listVo(List<T> oldList, Class<V> v) {
    
    
        if (oldList == null) {
    
    
            return null;
        }
        List<V> voList = new ArrayList<>();
        oldList.forEach(i -> voList.add(BeanDtoVoUtil.convert(i, v)));
        return voList;
    }


    /**
     * list<Entity> 集合对象转list<Vo> (Stream 方式)
     *
     * @param oldList
     * @param v
     * @return com.baomidou.mybatisplus.core.metadata.IPage<V>
     * @author ws
     * @mail [email protected]
     * @date 2020/4/23 0023 11:26
     */
    public static <T, V> List<V> listVoStream(List<T> oldList, Class<V> v) {
    
    
        if (oldList == null || oldList.size() == 0) {
    
    
            return null;
        }
        return oldList.stream().map(item -> (V) BeanDtoVoUtil.convert(item, v)).collect(Collectors.toList());
    }
}

三、使用 mapstruct

1、添加依赖

jar


<org.mapstruct.version>1.4.1.Final</org.mapstruct.version>


 <!-- mapstruct -->
        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct</artifactId>
            <version>${org.mapstruct.version}</version>
        </dependency>

编译配置

 <!-- mapstruct 插件 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                    <!-- 编译时使用 mapstruct + lombok -->
                    <annotationProcessorPaths>
                        <path>
                            <groupId>org.mapstruct</groupId>
                            <artifactId>mapstruct-processor</artifactId>
                            <version>${org.mapstruct.version}</version>
                        </path>
                        <path>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                            <version>${lombok.version}</version>
                        </path>
                    </annotationProcessorPaths>
                </configuration>
            </plugin>

2、添加 base 转换类

package com.ws.ldy.others.base.converter;

import com.baomidou.mybatisplus.core.metadata.IPage;

import java.util.List;

/**
 * 实体类转换工具, mapstruct ,子类自动生成 class代码
 * <P>
 *     D dto    -- 请求参数
 *     E entity -- 实体类,对应DB
 *     V vo     -- 响应参数
 * </P>
 * @author wangsong
 * @mail [email protected]
 * @date 2020/11/20 0020 12:02 
 * @version 1.0.0
 */
public abstract class BaseConverter<D, E, V> {
    
    

    public abstract D toDTO(E e);

    public abstract List<D> toDTO(List<E> e);

    public abstract E toEntity(D d);

    public abstract List<E> toEntity(List<D> d);

    public abstract V toVO(E e);

    public abstract List<V> toVO(List<E> e);

    /**
     * mybatis-plus Page 装换 , 需要连接数据库和依赖包,不做演示
     * @param page
     * @return
     */
    public IPage<V> toPage(IPage<E> page) {
    
    
        if (page == null) {
    
    
            return null;
        }
        return page.convert(this::toVO);
    }
}

3、对应实体类转换类


@Mapper(componentModel = "spring")
public abstract class AdminAuthorityConverter extends BaseConverter<AdminAuthorityDTO, AdminAuthority, AdminAuthorityVO>  {
    
    

}

项目启动会自动生成 impl 的编译后的代码, 自动实现 BaseConverter 中的方法, 使用泛型传递对象

在这里插入图片描述

4、使用


@Autowired
private XxxConverter  xxxConverter ;

// 根据方法自行选择
xxxConverter.toXXX(); 

  • 纯作者个人编写的项目(通用后台管理系统)–> https://gitee.com/wslxm/spring-boot-plus2 , 希望感兴趣的朋友可以看看,也希望大家提出一些建议来一起修正优化, 感谢支持

  • 本文到此结束,如果觉得有用,动动小手点赞或关注一下呗,将不定时持续更新更多的内容…,感谢大家的观看!

猜你喜欢

转载自blog.csdn.net/qq_41463655/article/details/109853416