DTO(Data Transfer Object)和 PO(Persistent Object)是两种不同的数据对象,它们在不同的场景下使用。
DTO 用于在不同的应用程序组件之间传输数据。它通常是轻量级的,只包含必要的字段,并且不包含任何业务逻辑。
PO 用于持久化数据到数据库。它通常是重量级的,包含所有必要的字段,并且包含业务逻辑。
DTO: 用于在不同的应用程序组件之间传输数据
PO: 用于持久化数据到数据库
DTO: 轻量级
PO: 重量级
DTO:只包含必要的字段
PO: 包含所有必要的字段
DTO:不包含任何业务逻辑
PO: 包含业务逻辑
在实际开发中,我们通常会使用 DTO 和 PO 来分离数据层和业务层。
DTO 位于数据层,用于在不同的应用程序组件之间传输数据。
PO 位于业务层,用于持久化数据到数据库。
是用于在不同的应用程序组件之间传输数据的轻量级对象。
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;
}
}
是用于持久化数据到数据库的重量级对象。
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;
}
}
org.modelmapper
modelmapper
3.1.1
import org.modelmapper.ModelMapper;
public UserPO testModelMapper(){
// 创建一个 ModelMapper 对象
ModelMapper modelMapper = new ModelMapper();
// 创建一个 DTO 对象
UserDTO userDTO = new UserDTO();
userDTO.setUsername("张三");
userDTO.setPassword("123456");
userDTO.setEmail("[email protected]");
// 将 DTO 对象转换为 PO 对象
UserPO userPO = modelMapper.map(userDTO, UserPO.class);
return userPO;
}
ma.glasnost.orika
orika-core
1.5.4
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
* @param
*/
private void filedMap(Class aType, Class bType, Map fields) {
ClassMapBuilder mapBuilder = mapperFactory.classMap(aType, bType);
if (fields != null && fields.size() > 0) {
Set> entries = fields.entrySet();
for (Map.Entry entry : entries) {
mapBuilder.field(entry.getKey(), entry.getValue());
}
}
mapBuilder.byDefault().register();
}
/**
* 对象的复制
*
* @param aType 源对象类型
* @param bType 目标对象类型
* @param fields 不同字段映射值
* @param source 要复制的对象
* @param
* @param
* @return
*/
public B beanCopy(Class aType, Class bType, Map fields, A source) {
filedMap(aType, bType, fields);
B target = mapperFactory.getMapperFacade().map(source, bType);
return target;
}
/**
* 对象的复制
*
* @param aType 源对象类型
* @param bType 目标对象类型
* @param source 要复制的对象
* @param
* @param
* @return
*/
public B beanCopy(Class aType, Class bType, A source) {
return beanCopy(aType, bType, null, source);
}
/**
* 集合的复制
*
* @param aType 源对象类型
* @param bType 目标对象类型
* @param fields 不同字段映射值
* @param source 要复制的对象
* @param
* @param
* @return
*/
public List beanListCopy(Class aType, Class bType, Map fields, Iterable source) {
filedMap(aType, bType, fields);
List bList = mapperFactory.getMapperFacade().mapAsList(source, bType);
return bList;
}
/**
* 集合的复制
*
* @param aType 源对象类型
* @param bType 目标对象类型
* @param source 要复制的对象
* @param
* @param
* @return
*/
public List beanListCopy(Class aType, Class bType, Iterable source) {
return beanListCopy(aType, bType, null, source);
}
}
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();
}
}
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", "[email protected]");
Map 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 orika1() {
Integer t = 100000;
List 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 map = new HashMap<>();
//map.put("age", "userAge"); //名称不同的属性之间映射
StopWatch watch = new StopWatch();
watch.start("orika");
List poList = orikaUtil.beanListCopy(UserDTO.class, UserPO.class, map, list);
System.out.println(poList);
watch.stop();
System.out.println("orika 复制用时:" + watch.getLastTaskTimeMillis());
return poList;
}
com.github.dozermapper
dozer-core
6.5.0
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 dozer() {
List 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 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;
}
参考地址:https://mapstruct.org/
参考地址:https://github.com/jmapper-framework/jmapper-core