关于JAVA Bean实体类对象pojo,vo,po,dto,entity之间的区别

本文深入解析JavaBean中的POJO, VO, PO, DTO, Entity等对象的区别与联系,阐述它们在业务层、持久层及数据传输中的作用,帮助理解各对象在实际开发中的应用场景。

关于JAVA Bean实体类对象pojo,vo,po,dto,entity之间的区别:
Pojo:
Pojo 普通的java对象 最基本的javaBean只有属性 加上属性的get,set方法,可以转化为PO,DTO,VO;比如说POJO在传输过程中就称为DTO;
Vo:
value object:值对象
通常用于业务层之间的数据传递,由new创建,由GC回收
和PO一样也是仅仅包含数据而已,但应是抽象出的业务对象,可以和表对应,也可以不是
Po:
persistant object:持久层对象
是ORM(Objevt Relational Mapping)框架中Entity,PO属性和数据库中表的字段形成一一对应关系
VO和PO,都是属性加上属性的get和set方法;表面看没什么不同,但代表的含义是完全不同的
DTO:
data transfer object:数据传输对象
是一种设计模式之间传输数据的软件应用系统,数据传输目标往往是数据访问对象从数据库中检索数据
数据传输对象与数据交互对象或数据访问对象之间的差异是一个以不具任何行为除了存储和检索的数据(访问和存取器)
简而言之,就是接口之间传递的数据封装
表里面有十几个字段:id,name,gender(M/F),age……
页面需要展示三个字段:name,gender(男/女),age
DTO由此产生,一是能提高数据传输的速度(减少了传输字段),二能隐藏后端表结构
在这里插入图片描述
Entity与vo,dto之间的关系:
1、entity 里的每一个字段,与数据库相对应,

2、vo 里的每一个字段,是和你前台 html 页面相对应,

3、dto 这是用来转换从 entity 到 vo,或者从 vo 到 entity 的中间的东西 。(DTO中拥有的字段应该是entity中或者是vo中的一个子集)

举个例子:

你的html页面上有三个字段,name,pass,age

你的数据库表里,有两个字段,name,pass , 注意没有 age。

而你的 vo 里,就应该有下面三个成员变量 ,因为对应 html 页面上三个字段 。

private string name;

private string pass;

private string age;

这个时候,你的 entity 里,就应该有两个成员变量 ,因为对应数据库表中的 2 个字段 。

private string name;

private string pass;

到了这里,好了,业务经理让你做这样一个业务“年龄大于 20 的才能存入数据库,这个时候,你就要用到 dto 了,

1)你要先从页面上拿到 vo,然后判断 vo 中的 age 是不是大于 20。

2)如果大于 20,就把 vo 中的 name 和 pass 拿出来,放到 dto 中。

3)然后在把 dto 中的 name 和 pass 原封不动的给 entity,然后根据 entity 的值,在传入数据库。

这就是他们三个的区别。

PS: dto 和 entity 里面的字段应该是一样的,dto 只是 entity 到 vo,或者 vo 到 entity 的中间过程,如果没有这个过程,你仍然可以做到增删改查,这是根据具体公司规范来的 。

Java 或其他面向对象的编程语言中,尤其是在分层架构(如 MVC、DDD)系统中,**DTOVOPOJOEntity** 是常见的实体类,它们分别用于不同的层次和场景。由于职责不同,这些对象之间经常需要进行数据转换。 --- ### ✅ 各种“对象”的定义与用途 | 缩写 | 全称 | 中文含义 | 使用场景 | |------|------|--------|---------| | **POJO** | Plain Old Java Object | 普通 Java 对象 | 任意简单 Java Bean,无限制 | | **Entity** | 实体类 | 与数据库表映射的对象 | 持久层(DAO/Repository),通常配合 JPA/Hibernate | | **DTO** | Data Transfer Object | 数据传输对象 | 跨层或跨服务传递数据(如 Controller 层输出) | | **VO** | Value Object / View Object | 值对象 / 视图对象 | 返回给前端的数据结构(可组合、脱敏、格式化) | > ⚠️ 注意:VO 在 DDD 中是“值对象”(不可变、无 ID),但在 Web 开发中常被当作 View Object 使用。 --- ## 🔄 实体之间的转换方式 ### 示例背景: 假设有一个用户管理系统: ```java // 1. Entity - 对应数据库 user 表 @Entity @Table(name = "user") public class UserEntity { @Id private Long id; private String username; private String password; // 敏感字段! private LocalDateTime createTime; // getters and setters... } // 2. DTO - 用于外部接口传输 public class UserDTO { private Long id; private String username; private LocalDateTime createTime; // getters and setters... } // 3. VO - 返回给前端的视图对象(可能包含额外信息) public class UserVO { private Long id; private String userName; private String createTimeFormatted; // 格式化时间字符串 // getters and setters... } // 4. POJO - 泛指上面所有类都可以称为 POJO(只要不是框架特殊类) ``` --- ## 🔧 转换方法一:手动 set/get(最安全,性能好) ```java public UserDTO toDTO(UserEntity entity) { if (entity == null) return null; UserDTO dto = new UserDTO(); dto.setId(entity.getId()); dto.setUsername(entity.getUsername()); dto.setCreateTime(entity.getCreateTime()); return dto; } public UserVO toVO(UserDTO dto) { UserVO vo = new UserVO(); vo.setId(dto.getId()); vo.setUserName(dto.getUsername()); vo.setCreateTimeFormatted( dto.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")) ); return vo; } ``` ✅ 优点:精确控制字段、类型转换、安全性高 ❌ 缺点:代码冗长,重复劳动 --- ## 🔧 转换方法二:使用 MapStruct(推荐!) [MapStruct](https://mapstruct.org/) 是一个注解处理器,在编译期生成类型安全的映射代码。 ### 添加依赖(Maven) ```xml <dependency> <groupId>org.mapstruct</groupId> <artifactId>mapstruct</artifactId> <version>1.5.2.Final</version> </dependency> ``` 启用注解处理(JDK 8+): ```xml <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <annotationProcessorPaths> <path> <groupId>org.mapstruct</groupId> <artifactId>mapstruct-processor</artifactId> <version>1.5.2.Final</version> </path> </annotationProcessorPaths> </configuration> </plugin> ``` ### 定义 Mapper 接口 ```java @Mapper public interface UserConvertMapper { UserConvertMapper INSTANCE = Mappers.getMapper(UserConvertMapper.class); @Mapping(source = "username", target = "userName") @Mapping(target = "createTimeFormatted", expression = "java( entity.getCreateTime() != null ? entity.getCreateTime().format(java.time.format.DateTimeFormatter.ofPattern(\"yyyy-MM-dd HH:mm\")) : null )" ) UserVO entityToVO(UserEntity entity); // 只复制公共字段(忽略 password) @Mapping(target = "password", ignore = true) UserDTO entityToDTO(UserEntity entity); UserEntity dtoToEntity(UserDTO dto); } ``` ### 使用示例 ```java UserEntity entity = userRepository.findById(1L); UserDTO dto = UserConvertMapper.INSTANCE.entityToDTO(entity); UserVO vo = UserConvertMapper.INSTANCE.entityToVO(entity); ``` ✅ 优点: - 编译期生成代码,无反射开销,性能极高 - 类型安全,IDE 支持自动跳转 - 支持复杂表达式、自定义转换逻辑 --- ## 🔧 转换方法三:使用 ModelMapper(基于反射) 轻量级自动映射工具,适合小型项目。 ### Maven 依赖 ```xml <dependency> <groupId>org.modelmapper</groupId> <artifactId>modelmapper</artifactId> <version>3.1.0</version> </dependency> ``` ### 使用 ```java ModelMapper modelMapper = new ModelMapper(); // 自动映射同名属性 UserDTO dto = modelMapper.map(entity, UserDTO.class); UserVO vo = modelMapper.map(dto, UserVO.class); ``` 可以配置规则: ```java modelMapper.createTypeMap(UserEntity.class, UserVO.class) .addMappings(mapper -> { mapper.map(src -> src.getUsername(), UserVO::setUserName); mapper.when(Conditions.isNotNull()) .map(src -> src.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")), UserVO::setCreateTimeFormatted); }); ``` ✅ 优点:简单快捷,支持动态配置 ❌ 缺点:运行时反射,性能略低;错误在运行时报出 --- ## 🔧 转换方法四:使用 Spring 的 `BeanUtils.copyProperties` 适用于字段名称一致的简单拷贝: ```java UserDTO dto = new UserDTO(); BeanUtils.copyProperties(entity, dto); // 同名属性自动复制 ``` ⚠️ 注意: - 不会自动跳过敏感字段(如 password),需手动排除 - 不支持嵌套对象深度拷贝 - 不支持类型不一致的字段(如 Date ↔ String) --- ## 🔧 转换方法五:Builder + 链式构造(函数式风格) ```java public static UserVO fromEntity(UserEntity e) { return UserVO.builder() .id(e.getId()) .userName(e.getUsername()) .createTimeFormatted(e.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"))) .build(); } ``` 前提是你用了 Lombok: ```java @Data @Builder @NoArgsConstructor @AllArgsConstructor public class UserVO { private Long id; private String userName; private String createTimeFormatted; } ``` --- ## 🏁 最佳实践建议 | 场景 | 推荐方案 | |------|----------| | 大型项目、高性能要求 | ✅ **MapStruct** | | 小型项目、快速开发 | ✅ **ModelMapper** 或 **Lombok + Builder** | | 简单赋值 | ✅ `BeanUtils.copyProperties`(注意过滤) | | 安全性要求高(脱敏) | 手动映射 or MapStruct 显式控制 | | 微服务间传输 | DTO + 序列化(JSON/Protobuf) | --- ## ❗常见问题规避 1. **不要把 Entity 直接暴露给前端** → 会导致敏感字段泄露(如 password)、数据库结构暴露。 2. **避免双向转换陷阱** → 不要轻易将 VOEntity 回写,容易引入非法数据。 3. **日期格式统一处理** → 使用 `@JsonFormat(pattern = "...")` 控制序列化输出。 4. **使用 IDE 插件辅助生成映射代码** → 如 IntelliJ 的 GenerateOLO plugin。 ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值