核心概念总览

POJO是 Plain Old Java Object 的缩写,直译为"普通的、老式的 Java 对象"。
它指的是一个简单的、纯粹的 Java 对象,不依赖于任何特定的框架、接口或注解。
下面都属于POJO
| 缩写 | 英文全称 | 中文释义 | 核心职责与使用场景 |
|---|---|---|---|
| PO | Persistent Object | 持久化对象 | 与数据库表结构一一对应,是数据层(DAO层)操作的核心。 |
| DO | Domain Object | 领域对象 | 在领域驱动设计(DDD) 中,代表业务领域中的核心实体。 |
| DTO | Data Transfer Object | 数据传输对象 | 用于进程/服务间的数据传输,通常用于远程调用等需要网络传输的场景。 |
| VO | View Object | 视图对象 | 用于展示层,封装前端页面需要的数据。 |
| BO | Business Object | 业务对象 | 在业务逻辑层,由多个PO或其它BO组合而成的复合业务对象。 |
详细解释与用法
1. PO (Persistent Object) - 持久化对象
-
是什么:PO 是与数据库表结构直接映射的 Java 对象。每个属性通常对应数据库表的一个字段。
-
怎么用:
-
主要在 DAO / Mapper 层 使用。
-
通过 MyBatis、Hibernate 等ORM框架进行增删改查操作。
-
不应包含任何业务逻辑,只是一个纯粹的数据载体。
-
-
示例:
假设有一张user表,有id,username,password字段。public class UserPO { private Long id; private String username; private String password; // getter, setter ... } // 在DAO/Mapper层使用 @Mapper public interface UserMapper { UserPO selectById(Long id); void insert(UserPO userPO); }
2. DO (Domain Object) - 领域对象
-
是什么:在领域驱动设计(DDD) 模式中,DO 是业务领域的核心实体,它不仅有数据,还包含与这个数据相关的业务行为(方法)。
-
怎么用:
-
在领域层 使用。
-
它强调的是封装性和行为,而不仅仅是数据的getter/setter。
-
在很多项目中,如果没有严格采用DDD,PO 和 DO 常常被混用,即一个类既是PO也是DO。但在严谨的架构中,它们应该分离。
-
-
示例:
一个银行领域的Account对象。public class AccountDO { private String accountNumber; private BigDecimal balance; // 行为:存款 public void deposit(BigDecimal amount) { if (amount.compareTo(BigDecimal.ZERO) <= 0) { throw new IllegalArgumentException("存款金额必须大于0"); } this.balance = this.balance.add(amount); } // 行为:取款(包含业务规则) public void withdraw(BigDecimal amount) { if (amount.compareTo(BigDecimal.ZERO) <= 0) { throw new IllegalArgumentException("取款金额必须大于0"); } if (this.balance.compareTo(amount) < 0) { throw new RuntimeException("余额不足"); } this.balance = this.balance.subtract(amount); } // getter ... }
3. DTO (Data Transfer Object) - 数据传输对象
-
是什么:用于不同进程或服务之间传输数据的对象。在网络传输(如RPC、REST API)时,它作为数据的容器。
-
怎么用:
-
在服务层(Service) 与 控制层(Controller) 之间,或者微服务之间传输。
-
它的设计不依赖于数据库表结构,而是根据传输需求来定义字段。
-
通常是一个纯数据结构,只有属性和getter/setter。
-
-
示例:
在用户注册时,前端传来的数据可能不包括id(由数据库生成),但包括密码确认字段。// 用于接收前端注册请求的DTO public class UserRegisterDTO { private String username; private String password; private String confirmPassword; // 这个字段在PO中不存在 // getter, setter ... }
4. VO (View Object) - 视图对象
-
是什么:专门为前端界面展示而设计的对象。
-
怎么用:
-
在 Controller 层 组装并返回给前端。
-
它的字段结构完全由前端页面的需求决定,通常会聚合多个PO/DTO的数据,或者对数据进行格式化。
-
绝对不能包含敏感信息(如密码)。
-
-
示例:
用户信息页面需要展示用户基本信息和他的订单数量。// 用于前端用户信息页面的VO public class UserProfileVO { private String username; private String nickname; private String avatarUrl; private Integer orderCount; // 这个数据可能来自Order服务 // getter, setter ... } // 在Controller层使用 @RestController public class UserController { @GetMapping("/user/profile") public UserProfileVO getUserProfile() { // ... 业务逻辑,组装VO return userProfileVO; } }
5. BO (Business Object) - 业务对象
-
是什么:在业务逻辑层(Service层) 使用的对象,它代表一个复合的业务实体,通常由多个PO聚合而成。
-
怎么用:
-
在 Service 层 内部使用,用于封装复杂的业务逻辑。
-
一个BO可能包含多个PO,或者包含对其他BO的引用。
-
-
示例:
“订单”这个业务对象,不仅包含订单本身的信息(OrderPO),还包含订单下的商品列表(OrderItemPO列表)和用户信息(UserPO)。public class OrderBO { // 来自 order 表 private OrderPO orderInfo; // 来自 order_item 表 private List<OrderItemPO> orderItems; // 来自 user 表 private UserPO user; // 可以在BO中计算业务属性,如总价 public BigDecimal getTotalAmount() { return orderItems.stream() .map(item -> item.getPrice().multiply(new BigDecimal(item.getQuantity()))) .reduce(BigDecimal.ZERO, BigDecimal::add); } // getter, setter ... }
数据流转与转换
在一个典型的分层架构中,数据的流转如下:
数据库 <-> PO <-> DAO层 <-> Service层 <-> Controller层 <-> 前端
-
DAO层:操作 PO。
-
Service层:
-
内部使用 BO 来封装业务。
-
接收来自Controller的 DTO。
-
返回 BO 或直接是 PO 给Controller。
-
-
Controller层:
-
接收前端传来的 DTO(通常通过
@RequestBody)。 -
调用Service层,获取 BO/PO。
-
将 BO/PO 转换为 VO,返回给前端。
-
关键点:各层之间的对象不应该直接传递,而应该进行转换。例如,Service层返回的BO,在Controller层要转换成VO再返回。这避免了底层数据结构的变化直接影响到上层(如API接口)。
转换工具:为了避免繁琐的 setter/getter 代码,推荐使用 MapStruct、BeanUtils(谨慎使用,注意性能和数据覆盖问题)、ModelMapper 等工具进行对象转换。
总结与最佳实践
-
职责分离:每个对象都有自己的职责,不要用一个对象贯穿所有层。这符合软件设计的“单一职责原则”。
-
避免“大而全”的对象:不要创建一个包含所有字段的“User”类,然后希望它在所有地方都能用。这会导致数据冗余、安全隐患(如把密码返回给前端)和强耦合。
-
按需定义:VO、DTO 的结构应根据前端和接口的需求来灵活定义,而不是死板地对应数据库。
-
理解本质而非记名字:在不同的公司或团队中,对这些对象的称呼可能不同(例如,有人把所有对象都叫POJO)。最重要的是理解它们背后的设计意图:在不同的上下文中,使用最适合的数据模型。
2006

被折叠的 条评论
为什么被折叠?



