Dish、DishVO 和 DishDTO

有了Dish,为什么还定义DishVO和DishDTO?

在软件开发中,定义Dish、DishVO和DishDTO是为了遵循分层设计思想和单一职责原则,解决不同场景下的数据传递和展示问题。它们的核心区别在于使用场景和职责不同。

我们通过一个具体场景来理解 Dish(实体类)、DishDTO(数据传输对象)、DishVO(视图对象)的区别:

假设我们有一个菜品管理系统,数据库 dish 表结构如下:

sql 复制代码
CREATE TABLE dish (
  id BIGINT PRIMARY KEY AUTO_INCREMENT,  -- 菜品ID
  name VARCHAR(100) NOT NULL,            -- 菜品名称
  price DECIMAL(10,2) NOT NULL,          -- 菜品价格
  category_id BIGINT NOT NULL,           -- 分类ID(关联分类表)
  image VARCHAR(255),                    -- 图片路径
  status INT NOT NULL,                   -- 状态(0-禁用,1-启用)
  create_time DATETIME NOT NULL,         -- 创建时间
  update_time DATETIME NOT NULL,         -- 更新时间
  create_user BIGINT NOT NULL,           -- 创建人ID
  update_user BIGINT NOT NULL            -- 更新人ID
);

1. Dish(实体类)

完全映射数据库表结构,用于和数据库交互:

java 复制代码
public class Dish {
    private Long id;           // 对应表中id
    private String name;       // 对应表中name
    private BigDecimal price;  // 对应表中price
    private Long categoryId;   // 对应表中category_id
    private String image;      // 对应表中image
    private Integer status;    // 对应表中status
    private LocalDateTime createTime;  // 对应表中create_time
    private LocalDateTime updateTime;  // 对应表中update_time
    private Long createUser;   // 对应表中create_user
    private Long updateUser;   // 对应表中update_user
    
    // getter/setter省略
}

使用场景:在 Service 层操作数据库时使用,例如 dishMapper.insert(dish) 保存数据到数据库。

2. DishDTO(数据传输对象)

用于接收前端传递的参数(按需定义,避免冗余):

示例 :新增菜品的 DishDTO

前端新增菜品时,无需传递 id(数据库自增)、createTime(后端生成)等字段,因此 DTO 只保留必要参数:

java 复制代码
public class DishSaveDTO {
    private String name;       // 必须:菜品名称
    private BigDecimal price;  // 必须:菜品价格
    private Long categoryId;   // 必须:分类ID
    private String image;      // 可选:图片路径
    private Integer status;    // 必须:状态(0-禁用,1-启用)
    
    // getter/setter省略
}

3. DishVO(视图对象)

用于返回给前端展示(包含前端需要的额外信息):

java 复制代码
public class DishVO {
    private Long id;           // 菜品ID(前端需要)
    private String name;       // 菜品名称(前端需要)
    private BigDecimal price;  // 菜品价格(前端需要)
    private String image;      // 图片路径(前端需要展示图片)
    private String categoryName;  // 额外:分类名称(前端需要显示"热菜"而非categoryId)
    private String statusStr;  // 额外:状态文字(前端显示"启用"而非1)
    
    // getter/setter省略
}

通过这种拆分,即使数据库表结构变化(如新增字段),只要前端需求不变,DTO 和 VO 可以无需修改,大大提高了代码的灵活性和可维护性。

相关推荐
jyOverQ5 分钟前
从零学 JVM(七):垃圾收集器详解——Serial、ParNew、Parallel、CMS 与 G1
java·jvm
liangbo713 分钟前
Spring系列11:切点表达式
java·spring
30955666631 分钟前
股票接口返回 404 与空数组的排查笔记:证书状态与级别参数
java·笔记·python·ios·iphone·股票数据api·股票数据接口
nice_lcj52034 分钟前
MySQL 存储引擎入门:InnoDB 和 MyISAM 到底怎么选
java·数据库·mysql·面试·innodb·存储引擎·myisam
文丑颜不良啊1 小时前
LeetCode2861~2880题目解析
java·leetcode
装不满的克莱因瓶1 小时前
设计模式之策略模式核心概念和应用场景
java·后端·设计模式·架构·系统架构·策略模式
晴天的雨.9921 小时前
【C++】继承篇
java·开发语言·c++
SomeOtherTime1 小时前
第 1 讲:内存布局与所有权解剖——栈帧、胖指针与“移动/拷贝”在汇编层面的真实面目
java·开发语言·汇编
qq_406981031 小时前
c++ lamda(三)Lambda表达式
java·前端·c++
头发还在的女程序员1 小时前
Java在线租房系统源码解析:Spring Boot+Vue 3+UniApp房源管理与预约看房方案
java·vue.js·spring boot·租房小程序·租房系统·租房软件