登录
/
注册
首页
论坛
其它
首页
科技
业界
安全
程序
广播
Follow
关于
签到
每天签到奖励2-10圆
导读
排行榜
TG频道
发帖说明
登录
/
注册
账号
自动登录
找回密码
密码
登录
立即注册
搜索
搜索
关闭
CSDN热搜
程序园
精品问答
技术交流
资源下载
本版
帖子
用户
软件
问答
教程
代码
写记录
VIP申请
VIP网盘
网盘
联系我们
发帖说明
每日签到
道具
勋章
任务
淘帖
动态
分享
留言板
导读
设置
我的收藏
退出
腾讯QQ
微信登录
返回列表
首页
›
业界区
›
业界
›
PO、VO、BO、DTO、DAO、POJO傻傻分不清楚
PO、VO、BO、DTO、DAO、POJO傻傻分不清楚
[ 复制链接 ]
豌笆
2025-8-14 16:04:07
前言
最近有小伙伴问我:O、VO、BO、DTO、DAO、POJO有什么区别?
第一眼看到,你可能也会有点懵。
这些对象的概念很多,确实容易搞混。
今天这篇文章跟大家一起聊聊这6种对象的含义、职责、区别和常见的坑,希望对你会有所帮助。
一、6种对象的职责边界
对象设计的本质是关注点分离
——每个对象只做一件事,且做好它!
1.1 PO
它的含义是Persistent Object,即持久化对象。
职责
:与数据库表严格1:1映射,
仅承载数据存储结构
特征
:
属性与表字段完全对应
无业务逻辑方法(仅有getter/setter)
代码示例
:
public class UserPO {
private Long id; // 对应表主键
private String name; // 对应name字段
}
复制代码
1.2 DAO
它的含义是Data Access Object,即数据访问对象。
职责
:
封装所有数据库操作
(CRUD),隔离业务与存储细节
特征
:
接口方法对应SQL操作
返回PO或PO集合
代码示例
:
public interface UserDao {
// 根据ID查询PO
UserPO findById(Long id);
// 分页查询
List<UserPO> findPage(@Param("offset") int offset, @Param("limit") int limit);
}
复制代码
底层原理
:DAO模式 = 接口 + 实现类 + PO
1.3 BO
它的含义是Business Object,即业务对象。
职责
:
封装核心业务逻辑
,聚合多个PO完成复杂操作
特征
:
包含业务状态机、校验规则
可持有多个PO引用
代码示例
:订单退款BO
public class OrderBO {
// 主订单数据
private OrderPO orderPO;
// 子订单项
private List<OrderItemPO> items;
// 业务方法:执行退款
public RefundResult refund(String reason) {
if (!"PAID".equals(orderPO.getStatus())) {
throw new IllegalStateException("未支付订单不可退款");
} // 计算退款金额、调用支付网关等 }
}
复制代码
1.4 DTO
它的含义是Data Transfer Object,即数据传输对象。
职责
:
跨层/跨服务数据传输
,屏蔽敏感字段
特征
:
属性集是PO的子集(如排除password字段)
支持序列化(实现Serializable)
代码示例
:用户信息DTO
public class UserDTO implements Serializable {
private Long id;
private String name;
}
复制代码
1.5 VO
它的含义是View Object,即视图对象。
职责
:
适配前端展示
,包含渲染逻辑
特征
:
属性可包含格式化数据(如日期转yyyy-MM-dd)
聚合多表数据(如订单VO包含用户名字)
代码示例
:
public class OrderVO {
private String orderNo;
private String createTime; // 格式化后的日期 private String userName; // 关联用户表字段
//状态码转文字描述
public String getStatusText() {
return OrderStatus.of(this.status).getDesc();
}
}
复制代码
1.6 POJO
它的含义是Plain Old Java Object,即普通Java对象。
职责
:
基础数据容器
,可扮演PO/DTO/VO角色
特征
:
只有属性+getter/setter
无框架依赖(如不继承Spring类)
典型实现
:Lombok简化代码
// 自动生成getter/setter
@Data
public class UserPOJO {
private Long id;
private String name;
}
复制代码
二、主流的对象流转模型
场景1
传统三层架构(DAO → DTO → VO)。
适用系统
:后台管理系统、工具类应用
核心流程
:
代码示例
:用户查询服务
// Service层
public UserDTO getUserById(Long id) {
UserPO userPO = userDao.findById(id); // 从DAO获取PO
UserDTO dto = new UserDTO();
dto.setId(userPO.getId());
dto.setName(userPO.getName()); // 过滤敏感字段
return dto; // 返回DTO
}
// Controller层
public UserVO getUser(Long id) {
UserDTO dto = userService.getUserById(id);
UserVO vo = new UserVO();
vo.setUserId(dto.getId());
vo.setUserName(dto.getName());
vo.setRegisterTime(formatDate(dto.getCreateTime())); // 格式化日期
return vo;
}
复制代码
优点
:简单直接,适合CRUD场景
缺点
:业务逻辑易泄漏到Service层
场景2
DDD架构(PO → DO → DTO → VO)。
适用系统
:电商、金融等复杂业务系统
核心流程
:
关键角色
:DO(Domain Object)替代BO
代码示例
:订单支付域
// Domain层:订单领域对象
public class OrderDO {
private OrderPO orderPO;
private PaymentPO paymentPO;
// 业务方法:支付校验
public void validatePayment() {
if (paymentPO.getAmount() < orderPO.getTotalAmount()) {
throw new PaymentException("支付金额不足");
}
}
}
// App层:协调领域对象
public OrderPaymentDTO pay(OrderPayCmd cmd) {
OrderDO order = orderRepo.findById(cmd.getOrderId());
order.validatePayment(); // 调用领域方法 return OrderConverter.toDTO(order); // 转DTO
}
复制代码
优点
:业务高内聚,适合复杂规则系统
缺点
:转换层级多,开发成本高
三、高效转换工具
手动转换对象?效率低且易错!
苏三在这里推荐三大利器。
3.1 MapStruct:编译期代码生成
原理
:APT注解处理器生成转换代码
示例
:PO转DTO
@Mapper
public interface UserConverter {
UserConverter INSTANCE = Mappers.getMapper(UserConverter.class);
@Mapping(source = "createTime", target = "registerDate")
UserDTO poToDto(UserPO po);
}
// 编译后生成UserConverterImpl.java
public class UserConverterImpl {
public UserDTO poToDto(UserPO po) {
UserDTO dto = new UserDTO();
dto.setRegisterDate(po.getCreateTime()); // 自动赋值!
return dto;
}
}
复制代码
优点
:零反射损耗,性能接近手写代码
开源地址
:https://github.com/mapstruct/mapstruct
3.2 Dozer + Lombok:注解驱动转换
组合方案
:
Lombok
:自动生成getter/setter
Dozer
:XML/注解配置字段映射
// Lombok注解
@Data
public class UserVO {
private String userId;
private String userName;
}
// 转换配置
<field>
userId
<b>id</b>
</field>
复制代码
适用场景
:字段名不一致的复杂转换
3.3 手动Builder模式:精细控制
适用场景
:需要动态构造的VO
public class OrderVOBuilder {
public OrderVO build(OrderDTO dto) {
return OrderVO.builder()
.orderNo(dto.getOrderNo())
.amount(dto.getAmount() + "元") // 动态拼接
.statusText(convertStatus(dto.getStatus()))
.build();
}
}
复制代码
四、避坑指南
坑1:PO直接返回给前端
// 致命错误:暴露数据库敏感字段!
public UserPO getUser(Long id) {
// 返回的PO包含password
return userDao.findById(id);
}
复制代码
解决方案
:
使用DTO过滤字段
注解屏蔽:@JsonIgnore
坑2:DTO中嵌入业务逻辑
public class OrderDTO {
// 错误!DTO不应有业务方法
public void validate() {
if (amount < 0)
throw new Exception();
}
}
复制代码
本质错误
:混淆DTO与BO的职责
坑3:循环嵌套转换
// OrderVO中嵌套List<ProductVO>
public class OrderVO {
// 嵌套对象
private List<ProductVO> products;
}
// 转换时触发N+1查询
orderVO.setProducts(order.getProducts()
.stream()
.map(p -> convertToVO(p)) // 循环查询数据库
.collect(toList()));
复制代码
优化方案
:批量查询 + 并行转换
五、如何选择对象模型?
总结
关于对象的4个核心原则:
单一职责
:
PO只存数据,BO只管业务,VO只负责展示——
绝不越界!
安全隔离
:
PO永不出DAO层(防数据库泄露)
VO永不出Controller(防前端逻辑污染服务)
性能优先
:
大对象转换用
MapStruct
(编译期生成代码)
嵌套集合用
批量查询
(杜绝N+1)
适度设计
:
10张表以内的系统:可用POJO一撸到底
百张表以上核心系统:
必须严格分层
对象设计没有银弹,
理解业务比套用模式更重要
!
当你在为对象命名纠结时,不妨回到业务的起点问一句:“它此刻的核心职责是什么?”
最后说一句(求关注,别白嫖我)
如果这篇文章对您有所帮助,或者有所启发的话,帮忙关注一下我的同名公众号:苏三说技术,您的支持是我坚持写作最大的动力。
求一键三连:点赞、转发、在看。
关注公众号:【苏三说技术】,在公众号中回复:进大厂,可以免费获取我最近整理的10万字的面试宝典,好多小伙伴靠这个宝典拿到了多家大厂的offer。
本文收录于我的技术网站:http://www.susan.net.cn
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
PO
VO
BO
DTO
DAO
相关帖子
惊呆了!全自动生成 Controller、Service、Dao、Mapper、VO!拒绝加班!!
笔记:Selenium 的 PO 模式
别再被VO、BO、PO、DTO、DO绕晕!今天用一段代码把它们讲透
Prisma不能优雅的支持DTO,试试Vona ORM吧
能够动态推断与生成DTO是Node生态的一个重要里程碑
vip免费申请,1年只需15美金$
回复
使用道具
举报
提升卡
置顶卡
沉默卡
喧嚣卡
变色卡
千斤顶
照妖镜
相关推荐
安全
惊呆了!全自动生成 Controller、Service、Dao、Mapper、VO!拒绝加班!!
1
1048
叭遭段
2025-06-01
安全
笔记:Selenium 的 PO 模式
0
892
蓟晓彤
2025-07-13
业界
别再被VO、BO、PO、DTO、DO绕晕!今天用一段代码把它们讲透
1
273
窝酴
2025-08-21
业界
Prisma不能优雅的支持DTO,试试Vona ORM吧
0
791
史华乐
2025-09-26
业界
能够动态推断与生成DTO是Node生态的一个重要里程碑
1
552
连热
2025-09-30
高级模式
B
Color
Image
Link
Quote
Code
Smilies
您需要登录后才可以回帖
登录
|
立即注册
回复
本版积分规则
回帖并转播
回帖后跳转到最后一页
签约作者
程序园优秀签约作者
发帖
豌笆
2025-8-14 16:04:07
关注
0
粉丝关注
15
主题发布
板块介绍填写区域,请于后台编辑
财富榜{圆}
anyue1937
9994893
dage888
999994
3934307807
992122
4
富账慕
9983
5
邹语彤
9982
6
刎唇
9993
7
匝抽
9986
8
聚怪闩
9960
9
孙淼淼
9977
10
烯八
9954
查看更多