PO与DTO互转

DTO(Data Transfer Object)和 PO(Persistent Object)是两种不同的数据对象,它们在不同的场景下使用。
DTO 用于在不同的应用程序组件之间传输数据。它通常是轻量级的,只包含必要的字段,并且不包含任何业务逻辑。
PO  用于持久化数据到数据库。它通常是重量级的,包含所有必要的字段,并且包含业务逻辑。

1、以下是 DTO 和 PO 的比较


    1.1、用途 

        DTO: 用于在不同的应用程序组件之间传输数据 
        PO:  用于持久化数据到数据库
    

    1.2、重量 

        DTO: 轻量级 
        PO:  重量级
    

     1.3、字段 

        DTO:只包含必要的字段 
        PO: 包含所有必要的字段

    1.4、业务逻辑 

        DTO:不包含任何业务逻辑 
        PO: 包含业务逻辑 

2、分层

    在实际开发中,我们通常会使用 DTO 和 PO 来分离数据层和业务层。

    DTO 位于数据层,用于在不同的应用程序组件之间传输数据。
    PO 位于业务层,用于持久化数据到数据库。

3、PO与DTO互转示例


3.1、UserDTO

是用于在不同的应用程序组件之间传输数据的轻量级对象。

public class UserDTO {

    private String username;
    private String password;
    private String email;
    public UserDTO(){}

    public UserDTO(String username, String password, String email) {
        this.username = username;
        this.password = password;
        this.email = email;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}

3.2、UserPO  

是用于持久化数据到数据库的重量级对象。

public class UserPO {

    private Long id;
    private String username;
    private String password;
    private String email;
    public UserPO(){}

    public UserPO(Long id, String username, String password, String email) {
        this.id = id;
        this.username = username;
        this.password = password;
        this.email = email;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}

4、使用ModelMapper

4.1、在pom.xml文件中,引入ModelMapper依赖

<dependency>
	<groupId>org.modelmapper</groupId>
	<artifactId>modelmapper</artifactId>
	<version>3.1.1</version>
</dependency>

    4.2、示例

    import org.modelmapper.ModelMapper;
    public UserPO testModelMapper(){
        // 创建一个 ModelMapper 对象
        ModelMapper modelMapper = new ModelMapper();

        // 创建一个 DTO 对象
        UserDTO userDTO = new UserDTO();
        userDTO.setUsername("张三");
        userDTO.setPassword("123456");
        userDTO.setEmail("zhangsan@example.com");

        // 将 DTO 对象转换为 PO 对象
        UserPO userPO = modelMapper.map(userDTO, UserPO.class);

        return userPO;
    }

5、使用orika

5.1、在pom.xml文件中,引入orika依赖

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

5.2、 示例

5.2.1、OrikaUtil 工具类
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
 * https://www.cnblogs.com/zys2019/p/17005798.html#_label1_2
 */
@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);
    }
}
5.2.2、配置类
import ma.glasnost.orika.MapperFactory;
import ma.glasnost.orika.impl.DefaultMapperFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * orika
 */
@Configuration
public class MapperFactoryAutoConfig {

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

}
5.2.3、测试示例
import cn.example.demo.dto.UserDTO;
import cn.example.demo.dto.UserPO;
import cn.example.demo.utils.OrikaUtil;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StopWatch;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


@Autowired
private OrikaUtil orikaUtil;

/**
* 单个对象
* @return
*/
public UserPO orika0() {
        UserDTO userDto = new UserDTO("orika0", "123", "zhansan@qq.com");
        Map<String, String> map = new HashMap<>();
        //map.put("password", "password1");//有差异的属性名称
        UserPO userPo = orikaUtil.beanCopy(UserDTO.class, UserPO.class, map, userDto);
        System.out.println(userPo);
        return userPo;
}


/**
* 对象列表转换
* 10万条耗时 583 ms
*/
public List<UserPO> orika1() {
        Integer t = 100000;
        List<UserDTO> list = new ArrayList<>();
        for (int i = 0; i < t; i++) {
            UserDTO userDto = new UserDTO("orika" + i, "111"+ i, "orika"+ i+"@qq.com");
            list.add(userDto);
        }

        Map<String, String> map = new HashMap<>();
        //map.put("age", "userAge"); //名称不同的属性之间映射
        StopWatch watch = new StopWatch();
        watch.start("orika");
        List<UserPO> poList = orikaUtil.beanListCopy(UserDTO.class, UserPO.class, map, list);
        System.out.println(poList);
        watch.stop();
        System.out.println("orika 复制用时:" + watch.getLastTaskTimeMillis());

        return poList;
}

6、使用 dozer

6.1、在pom.xml文件中,引入dozer依赖

<dependency>
  <groupId>com.github.dozermapper</groupId>
  <artifactId>dozer-core</artifactId>
  <version>6.5.0</version>
</dependency>

6.2、示例

import cn.example.demo.dto.UserDTO;
import cn.example.demo.dto.UserPO;
import com.github.dozermapper.core.DozerBeanMapperBuilder;
import com.github.dozermapper.core.Mapper;
import org.springframework.util.StopWatch;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

//参考地址:
//https://dozermapper.github.io/user-guide.pdf
//https://www.jb51.net/article/239801.htm
//https://blog.csdn.net/weixin_33786077/article/details/94759020

public List<UserPO> dozer() {
        List<UserDTO> list = new ArrayList<>();
        for (int i = 0; i < 100000; i++) {
            UserDTO userDto = new UserDTO("dozer" + i, "111"+ i, "dozer"+ i+"@qq.com");
            list.add(userDto);
        }


        List<UserPO> poList = new ArrayList<>();
        Mapper mapper = DozerBeanMapperBuilder.buildDefault();
        StopWatch watch = new StopWatch();
        watch.start("dozer");
        list.stream().forEach(item -> {
            UserPO userPo = mapper.map(item, UserPO.class);
            poList.add(userPo);
            System.out.println("userPo:" + item.hashCode());
        });
        watch.stop();
        System.out.println("dozer复制用时:" + watch.getLastTaskTimeMillis());
   return poList;
}

7、MapStruct

参考地址:https://mapstruct.org/

8、JMapper

参考地址:https://github.com/jmapper-framework/jmapper-core

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值