[DDD架构]不同数据模型DTO、VO、PO、DAO、DO的含义
在学习DDD和之前的相关资料中,尝尝能看见DTO、VO、PO等各种各样的object,于是一起整理下方便记忆。
精要版本
各种object一共包含DTO、VO、PO、DAO、DO,其含义可以通过英文全称很方便的记忆理解。
从接口到数据持久化层理解一波。
视图对象(View Object, VO),用于封装展示层指定页面或组件的数据。 人话版VO就是接口返回的对象。
数据传输对象( Data Transfer Object, DTO),用于前端应用与微服务应用层或者微服务之间的数据组装和传输,是应用之间数据传输的载体。人话版DTO就是接口传入的请求参数的对象。
数据访问对象(Data Access Object,DAO),用于查询到数据,隔离服务和持久化层,提供CRUD方法。人话版本DAO就是用来提供CRUD方法的类(一般没有类成员变量),避免直接使用service层直接操作增删改查数据库。
领域对象( Domain Object, DO),微服务运行时核心业务对象的载体, DO 一般包括实体或值对象。在开发过程中可以按需看是否需要创建DO类,或许可以创建DO类直接引用PO类的指针?
数据持久化对象 (Persistent Object, PO),与数据库结构一一映射,它是数据持久化过程中的数据载体。微服务基础层的主要数据对象是PO。人话版PO就是数据库查询的那几个dbmodels类。
《DDD实战课》老师给的建议:
在设计时,先建立DO和PO的映射关系,大多数情况下DO和PO是一一对应的。但也有DO和PO多对多的情况。
在DO和PO数据转换时,需要进行数据重组。对于DO对象较多复杂的数据转换操作,你可以在聚合用工厂模式来实现。
- 当DO数据需要持久化时,先将DO转换为PO对象,由仓储实现服务完成数据库持久化操作。
- 当DO需要构建和数据初始化时,仓储实现服务先从数据库获取PO对象,将PO转换为DO后,完成DO数据构建和初始化。
领域层主要是DO对象。DO是实体和值对象的数据和业务行为载体,承载着基础的核心业务逻辑,多个依赖紧密的DO对象构成聚合。领域层DO对象在持久化时需要转换为PO对象。
应用层主要对象有DO对象,但也可能会有DTO对象。应用层在进行不同聚合的领域服务编排时,一般建议采用聚合根ID的引用方式,应尽量避免不同聚合之间的DO对象直接引用,避免聚合之间产生依赖。
在涉及跨微服务的应用服务调用时,在调用其他微服务的应用服务前,DO会被转换为DTO,完成跨微服务的DTO数据组装,因此会有DTO对象。
在前端调用后端应用服务时,用户接口层先完成DTO到DO的转换,然后DO作为应用服务的参数,传导到领域层完成业务逻辑处理。 用户接口层主要完成DO和DTO的互转,完成微服务与前端应用数据交互和转换。
facade接口服务在完成后端应用服务封装后,会对多个DO对象进行组装,转换为DTO对象,向前端应用完成数据转换和传输。 facade接口服务在接收到前端应用传入的DTO后,完成DTO向多个DO对象的转换,调用后端应用服务完成业务逻辑处理。 前端应用主要是VO对象。展现层使用VO进行界面展示,通过用户接口层与应用层采用DTO对象进行数据交互。
全面版本和记忆方法(DS生成)
DTO、VO、DAO、PO是分层架构中的核心概念,用于解耦数据模型与业务逻辑。以下是它们的含义及理解记忆方法:
1. PO(Persistent Object)持久化对象
-
定义:与数据库表结构直接映射的对象,每个属性对应表的字段。
-
用途:
- 用于DAO层与数据库交互,通过ORM框架(如MyBatis、Hibernate)操作21356。
- 仅包含数据字段和基本getter/setter方法,无业务逻辑。
-
示例:
public class UserPO {private Long id; // 对应数据库表的主键private String username;private String password; }
-
记忆关键:
- Persistent(持久化) → 数据库表结构的镜像。
- 与数据库操作强关联,如SQL查询、插入等。
2. DTO(Data Transfer Object)数据传输对象
-
定义:跨层或跨服务传输数据的载体,屏蔽内部数据细节。
-
用途:
- 前端与后端交互:如Controller接收
@RequestBody
参数或返回REST响应21543。 - 微服务通信:避免暴露领域模型或数据库结构,仅传递必要字段133056。
- 前端与后端交互:如Controller接收
-
特点:
- 可聚合多个PO的字段(如用户信息+订单列表)。
- 脱敏敏感数据(如密码隐藏)或裁剪冗余字段1630。
-
示例:
public class UserDTO {private String username;private String email; // 不包含密码字段 }
-
记忆关键:
- Data Transfer → 数据搬运工,负责层间传输。
- 类似快递包裹,只装必要物品,保护隐私。
3. VO(View Object)视图对象
-
定义:面向前端展示的定制化数据模型,适配页面需求。
-
用途:
- 返回给前端的JSON数据,如格式化日期、金额等21530。
- 聚合多表数据(如用户信息+头像URL)1656。
-
特点:
- 字段可能与DTO不同(如性别显示为“男/女”而非数字)。
- 包含展示逻辑(如状态码转文字描述)3047。
-
示例:
public class UserVO {private String username;private String createTime; // 格式化为"yyyy-MM-dd" }
-
记忆关键:
- View → 前端视角,专为页面定制。
- 类似商品包装,吸引用户而非仅存储。
4. DAO(Data Access Object)数据访问对象
-
定义:封装数据库操作的接口,隔离业务层与持久层。
-
用途:
- 提供CRUD方法(如
save()
、findById()
),通过Mapper或ORM执行SQL25647。 - 协调事务管理、连接池等底层细节4757。
- 提供CRUD方法(如
-
示例:
public interface UserDAO {UserPO findById(Long id);void save(UserPO user); }
-
记忆关键:
- Data Access → 数据访问的“服务员”,负责与数据库对话。
- 类似餐厅服务员,后厨(数据库)与顾客(业务层)的桥梁。
如何理解与记忆?
-
按分层架构划分:
- DAO层:操作数据库(PO + DAO)。
- Service层:处理业务逻辑(DTO + BO)。
- Controller层:接收请求/返回响应(DTO ↔ VO)。
-
类比现实场景:
- PO:仓库中的原始货物(数据库记录)。
- DTO:物流运输中的标准包装(跨层传输)。
- VO:商店货架上的精美陈列(前端展示)。
- DAO:仓库管理员(执行存取操作)。
-
转换流程示例:
用户请求 → VO接收 → 转为DTO → Service处理 → DAO操作PO → 数据库读写 → 反向转换返回VO。
常见混淆点
-
DTO vs VO:
- DTO是服务层与展示层的协议,VO是最终展示的数据。
- DTO可能被多个VO复用,VO可能组合多个DTO。
-
PO vs Entity:
- 两者常等同,但Entity在DDD中可能包含业务逻辑。
通过理解分层职责和实际场景,可以清晰区分这些概念。在简单系统中,DTO和VO可合并,但需在复杂场景中严格分离以保持扩展性。