关注:CodingTechWork
引言
在 Java 开发中,DTO(Data Transfer Object)
和 Entity
(实体类)是常见的两种数据模型。DTO 通常用于数据传输,而 Entity 用于与数据库交互。在实际开发中,经常需要在 DTO 和 Entity 之间进行数据的拷贝和转换。本文将介绍几种常见的工具类和自定义方式来实现这种转换,并提供相应的代码示例。
手动拷贝
手动拷贝是最直接的方式,通过编写代码逐个字段进行赋值。
代码示例
public class UserEntity {
private Long id;
private String name;
private Integer age;
// 省略 getter 和 setter 方法
}
public class UserDTO {
private Long id;
private String name;
private Integer age;
// 省略 getter 和 setter 方法
}
public class UserConverter {
public static UserDTO toDTO(UserEntity entity) {
UserDTO dto = new UserDTO();
dto.setId(entity.getId());
dto.setName(entity.getName());
dto.setAge(entity.getAge());
return dto;
}
public static UserEntity toEntity(UserDTO dto) {
UserEntity entity = new UserEntity();
entity.setId(dto.getId());
entity.setName(dto.getName());
entity.setAge(dto.getAge());
return entity;
}
}
优点
- 精确控制字段的转换逻辑。
- 不依赖外部库。
缺点
- 代码冗长,容易出错。
- 当字段较多时,维护成本较高。
使用 BeanUtils
Apache Commons BeanUtils 提供了 BeanUtils.copyProperties 方法,可以简化字段拷贝。
代码示例
import org.apache.commons.beanutils.BeanUtils;
public class UserConverter {
public static UserDTO toDTO(UserEntity entity) throws Exception {
UserDTO dto = new UserDTO();
BeanUtils.copyProperties(dto, entity);
return dto;
}
public static UserEntity toEntity(UserDTO dto) throws Exception {
UserEntity entity = new UserEntity();
BeanUtils.copyProperties(entity, dto);
return entity;
}
}
优点
- 简化代码,减少手动拷贝的工作量。
缺点
- 需要额外引入
Apache Commons BeanUtils
库。 - 性能相对较低,因为它是通过反射实现的。
使用 Dozer
Dozer 是一个开源的 Java Bean
映射框架,支持复杂的数据映射。
代码示例
import org.dozer.DozerBeanMapper;
public class UserConverter {
private static final DozerBeanMapper mapper = new DozerBeanMapper();
public static UserDTO toDTO(UserEntity entity) {
return mapper.map(entity, UserDTO.class);
}
public static UserEntity toEntity(UserDTO dto) {
return mapper.map(dto, UserEntity.class);
}
}
优点
- 支持复杂的数据映射,包括嵌套对象和集合。
- 配置灵活,可以通过 XML 或注解进行映射配置。
缺点
- 需要额外引入 Dozer 库。
- 配置较为复杂,尤其是对于复杂的映射场景。
使用 MapStruct
MapStruct 是一个基于注解的代码生成工具,可以在编译时生成数据映射代码。
代码示例
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
@Mapper
public interface UserMapper {
UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);
UserDTO toDTO(UserEntity entity);
UserEntity toEntity(UserDTO dto);
}
优点
- 在编译时生成代码,性能高。
- 支持复杂的数据映射,包括嵌套对象和集合。
- 代码简洁,易于维护。
缺点
- 需要额外引入
MapStruct
库。 - 需要配置注解,学习成本较高。
使用 ModelMapper
ModelMapper
是一个简单易用的 Java Bean
映射库,支持自动映射和自定义映射。
代码示例
import org.modelmapper.ModelMapper;
public class UserConverter {
private static final ModelMapper modelMapper = new ModelMapper();
public static UserDTO toDTO(UserEntity entity) {
return modelMapper.map(entity, UserDTO.class);
}
public static UserEntity toEntity(UserDTO dto) {
return modelMapper.map(dto, UserEntity.class);
}
}
优点
- 简单易用,支持自动映射。
- 支持自定义映射规则。
缺点
- 需要额外引入
ModelMapper
库。 - 性能相对较低,因为它是通过反射实现的。
自定义工具类
如果项目中对性能要求较高,且字段映射规则较为固定,可以自定义工具类来实现字段拷贝。
代码示例
public class UserConverter {
public static UserDTO toDTO(UserEntity entity) {
return new UserDTO(entity.getId(), entity.getName(), entity.getAge());
}
public static UserEntity toEntity(UserDTO dto) {
return new UserEntity(dto.getId(), dto.getName(), dto.getAge());
}
}
优点
- 性能高,因为是直接调用构造函数。
- 代码简洁,易于维护。
缺点
- 不支持复杂的数据映射。
- 如果字段较多,代码量会增加。
总结
在实际开发中,选择哪种方式取决于项目需求和团队的技术栈。
- 如果项目对性能要求较高,推荐使用
MapStruct
或自定义工具类; - 如果项目对开发效率要求较高,推荐使用
ModelMapper
或BeanUtils
。