网站Logo 苏叶的belog

Spring开发中几种数据模型

wdadwa
1
2026-03-05

一、解整体架构

在典型的 Spring Boot 项目中,一般会分层:

Controller 层  (接口层)
      │
      ▼
Service 层 (业务层)
      │
      ▼
DAO / Repository 层 (数据访问层)
      │
      ▼
Database (数据库)

不同层会使用不同的对象:

Controller
   │
   ├── DTO  (接收/返回接口数据)
   │
Service
   │
   ├── BO   (业务对象)
   │
DAO
   │
   ├── PO   (数据库映射对象)
   │
其他
   │
   ├── VO   (展示对象)
   └── POJO (普通Java对象)

简单记忆:

对象作用
PO数据库对象
DTO传输对象
VO展示对象
BO业务对象
DAO数据访问对象
POJO普通Java对象

二、PO(Persistent Object)

PO = Persistent Object(持久化对象)

作用:

数据库表 → Java对象

通常用于 ORM 映射(如 MyBatis / JPA)。

特点:

  • 字段与数据库字段 一一对应
  • 一般只包含 属性 + getter/setter
  • 不包含业务逻辑

示例

数据库表:

user
---------
id
name
age
create_time

PO:

public class UserPO {

    private Long id;

    private String name;

    private Integer age;

    private LocalDateTime createTime;

    // getter/setter
}

在 DAO 中使用:

@Mapper
public interface UserMapper {

    UserPO selectById(Long id);

    void insert(UserPO user);
}

总结:

PO = 数据库表结构映射对象

三、DTO(Data Transfer Object)

DTO = 数据传输对象

主要用于:

服务之间传输数据
或者
Controller 接收/返回数据

为什么需要 DTO?

因为:数据库对象不能直接暴露给外部

例如:

UserPO
id
name
password
createTime

但是接口不能返回 password

所以需要 DTO。

示例:

public class UserDTO {

    private Long id;

    private String name;

}

Controller:

@RestController
@RequestMapping("/user")
public class UserController {

    @GetMapping("/{id}")
    public UserDTO getUser(@PathVariable Long id){
        return userService.getUser(id);
    }

}

Service:

public UserDTO getUser(Long id){

    UserPO user = userMapper.selectById(id);

    UserDTO dto = new UserDTO();
    dto.setId(user.getId());
    dto.setName(user.getName());

    return dto;
}

总结:

DTO = 用于接口 / RPC / 服务之间传输数据

四、VO(View Object)

VO = View Object(视图对象)

作用:

专门用于返回给前端

VO 和 DTO 很多人混用,但严格来说:

对象作用
DTO传输
VO前端展示

VO 更偏向:

UI 展示数据

例如:

用户列表接口

前端需要:

id
name
age
订单数量
VIP等级

这些可能来自多个表。

VO 示例:

public class UserVO {

    private Long id;

    private String name;

    private Integer age;

    private Integer orderCount;

    private String vipLevel;
}

Controller:

@GetMapping("/list")
public List<UserVO> list(){
    return userService.listUsers();
}

总结:

VO = 给前端展示的数据结构

五、BO(Business Object)

BO = Business Object(业务对象)

作用:

封装业务逻辑

BO 通常存在于:

Service 层

例如:

用户注册业务:

校验
创建用户
创建钱包
发送消息

BO:

public class UserBO {

    private String name;

    private String password;

    private String phone;

}

Service:

public void register(UserBO userBO){

    // 业务校验
    if(userBO.getPassword().length() < 6){
        throw new RuntimeException("密码太短");
    }

    UserPO user = new UserPO();
    user.setName(userBO.getName());
    user.setPassword(userBO.getPassword());

    userMapper.insert(user);
}

总结:

BO = 业务逻辑处理对象

六、DAO(Data Access Object)

DAO = 数据访问对象

作用:

负责操作数据库

DAO 层:

SQL
CRUD
数据库访问

示例:

public interface UserDAO {

    UserPO selectById(Long id);

    void insert(UserPO user);

    void update(UserPO user);

    void delete(Long id);

}

在 MyBatis 中:

DAO = Mapper

例如:

@Mapper
public interface UserMapper {
}

总结:

DAO = 数据库访问层

七、POJO(Plain Old Java Object)

POJO = 普通 Java 对象

含义:

没有任何框架依赖的普通Java类

例如:

public class User {

    private String name;

    private Integer age;

}

特点:

  • 不继承框架类
  • 不实现特殊接口
  • 普通 Java 类

实际上:

PO
DTO
VO
BO

本质上都是 POJO

关系:

POJO
 ├── PO
 ├── DTO
 ├── VO
 └── BO

八、完整流程示例

假设:

查询用户接口

流程:

前端请求
   │
   ▼
Controller
   │ DTO
   ▼
Service
   │ BO
   ▼
DAO
   │ PO
   ▼
Database

代码流程:

1 Controller

@GetMapping("/{id}")
public UserVO getUser(@PathVariable Long id){

    UserBO userBO = userService.getUser(id);

    UserVO vo = new UserVO();
    vo.setName(userBO.getName());

    return vo;
}

2 Service

public UserBO getUser(Long id){

    UserPO user = userMapper.selectById(id);

    UserBO bo = new UserBO();
    bo.setName(user.getName());

    return bo;
}

3 DAO

UserPO selectById(Long id);

九、真实企业项目结构

project
 ├── controller
 │     └── UserController
 │
 ├── service
 │     └── UserService
 │
 ├── dao
 │     └── UserMapper
 │
 ├── entity
 │     └── UserPO
 │
 ├── dto
 │     └── UserDTO
 │
 ├── vo
 │     └── UserVO
 │
 └── bo
       └── UserBO

十、很多公司其实是这样用的(真实情况)

实际上很多公司会简化:

PO = Entity
DTO = Request / Response
VO = Response

甚至很多项目只有:

Entity
DTO

或者:

Entity
VO

因为对象太多会导致:

代码膨胀

所以需要根据项目复杂度决定。

十一、总结

一张图记住:

数据库
   │
   ▼
PO (数据库对象)
   │
DAO (数据访问)
   │
BO (业务处理)
   │
DTO (数据传输)
   │
VO (前端展示)

口诀:

PO  → 数据库
DAO → 数据访问
BO  → 业务处理
DTO → 数据传输
VO  → 页面展示
POJO → 普通Java对象
动物装饰