springboot中entity、dto、vo的通俗理解与实战
刚接触springboot开发时,你是不是也有过这样的困惑:明明数据库表对应一个实体类就够了,为什么还要搞出dto、vo这些"花里胡哨"的东西?直接把数据库实体类传到前端不行吗?
答案是:不行。就像我们寄快递时,不会把家里的保险箱直接寄出去,而是会把里面的东西拿出来装在快递盒里(选需要的东西、去掉敏感信息)。entity、dto、vo就是这套"数据包装"的不同容器,各自有明确的使用场景。今天咱们用最直白的案例,把这些概念讲清楚。
一、entity:和数据库"一对一"的"原始数据袋"
定义:entity(实体类)是数据库表的"镜像",字段和数据库表一一对应,它的使命就是和数据库打交道——存数据、取数据。
核心作用:作为持久层(repository层)操作的载体,负责数据在java对象和数据库表之间的映射。
实战案例:用户表对应的entity
假设数据库有张user表,结构如下:
| 字段名 | 类型 | 说明 |
|---|---|---|
| id | bigint | 主键 |
| username | varchar(50) | 用户名 |
| password | varchar(100) | 加密密码 |
| varchar(100) | 邮箱 | |
| create_time | datetime | 创建时间 |
| 对应的entity类: |
import jakarta.persistence.*;
import lombok.data;
import java.time.localdatetime;
// 与数据库表user映射
@entity
@table(name = "user")
@data // lombok注解,自动生成getter、setter等
public class userentity {
// 主键
@id
@generatedvalue(strategy = generationtype.identity)
private long id;
// 用户名,对应表中username字段
private string username;
// 密码(加密存储),对应表中password字段
private string password;
// 邮箱,对应表中email字段
private string email;
// 创建时间,对应表中create_time字段
@column(name = "create_time")
private localdatetime createtime;
}注意:entity只应该在dao层(数据访问层)和service层内部使用,绝对不能直接传到前端!因为它包含敏感信息(如password)和前端可能不需要的字段(如createtime)。
二、dto:服务间数据传输的"快递盒"
定义:dto(data transfer object,数据传输对象)用于不同服务之间、或服务内部不同层之间传递数据。它就像快递盒,只装对方需要的数据,不多不少。
核心作用:1. 减少数据传输量(只传必要字段);2. 隔离不同服务的实体结构(避免一个服务改实体影响另一个服务)。
实战案例:用户注册的dto
用户注册时,前端需要传用户名、密码、邮箱,但不需要传id(数据库自增)和createtime(后端生成)。这时候就需要一个userregisterdto:
import lombok.data;
import jakarta.validation.constraints.notblank;
import jakarta.validation.constraints.email;
@data
public class userregisterdto {
// 用户名不能为空
@notblank(message = "用户名不能为空")
private string username;
// 密码不能为空
@notblank(message = "密码不能为空")
private string password;
// 邮箱格式要正确
@notblank(message = "邮箱不能为空")
@email(message = "邮箱格式不正确")
private string email;
}service层接收dto并转换为entity:
@service
public class userservice {
@autowired
private userrepository userrepository;
public void register(userregisterdto registerdto) {
// 1. dto转换为entity
userentity userentity = new userentity();
userentity.setusername(registerdto.getusername());
// 密码加密(实际开发中一定要加密!)
userentity.setpassword(encryptpassword(registerdto.getpassword()));
userentity.setemail(registerdto.getemail());
userentity.setcreatetime(localdatetime.now());
// 2. 保存到数据库
userrepository.save(userentity);
}
// 密码加密方法(示例)
private string encryptpassword(string rawpassword) {
return new bcryptpasswordencoder().encode(rawpassword);
}
}三、vo:给前端展示的"最终商品"
定义:vo(view object,视图对象)是专门给前端页面展示用的数据对象。它就像商店里的商品展示,只展示用户想看到的信息,隐藏内部细节。
核心作用:定制前端需要的展示数据,比如字段别名、组合字段等。
实战案例:用户详情的vo
前端展示用户详情时,需要id、用户名、邮箱,但不需要password和createtime。这时候用uservo:
import lombok.data;
@data
public class uservo {
private long id;
private string username;
private string email;
// 可以增加前端需要的组合字段,比如"用户标签"
private string usertag;
}service层查询entity并转换为vo:
@service
public class userservice {
@autowired
private userrepository userrepository;
public uservo getuserdetail(long userid) {
// 1. 从数据库查询entity
userentity userentity = userrepository.findbyid(userid)
.orelsethrow(() -> new runtimeexception("用户不存在"));
// 2. entity转换为vo
uservo uservo = new uservo();
uservo.setid(userentity.getid());
uservo.setusername(userentity.getusername());
uservo.setemail(userentity.getemail());
// 定制前端需要的组合字段
uservo.setusertag("普通用户");
return uservo;
}
}controller层返回vo给前端:
@restcontroller
@requestmapping("/user")
public class usercontroller {
@autowired
private userservice userservice;
@getmapping("/{userid}")
public uservo getuserdetail(@pathvariable long userid) {
return userservice.getuserdetail(userid);
}
}四、三者转换的"小技巧"
手动转换(setter/getter)虽然直观,但字段多了很麻烦。实际开发中推荐用工具类:
- modelmapper:自动映射同名字段,支持自定义映射规则。
- mapstruct:编译期生成映射代码,性能更好,需要写接口。
modelmapper示例:
// 1. 引入依赖
<dependency>
<groupid>org.modelmapper</groupid>
<artifactid>modelmapper</artifactid>
<version>3.2.0</version>
</dependency>
// 2. 配置bean
@configuration
public class modelmapperconfig {
@bean
public modelmapper modelmapper() {
return new modelmapper();
}
}
// 3. 服务中使用
@service
public class userservice {
@autowired
private modelmapper modelmapper;
public uservo getuserdetail(long userid) {
userentity userentity = userrepository.findbyid(userid).orelsethrow(...);
// 自动转换entity到vo
return modelmapper.map(userentity, uservo.class);
}
}五、总结:一句话分清三者
| 对象类型 | 使用场景 | 核心目的 |
|---|---|---|
| entity | dao层 ↔ 数据库 | 和数据库表一一对应,负责数据持久化 |
| dto | 服务间/层间数据传输 | 减少传输量,隔离服务依赖 |
| vo | service层 ↔ 前端 | 定制前端展示数据,隐藏敏感信息 |
| 记住:边界清晰是代码整洁的关键。用对entity、dto、vo,能让你的springboot项目结构更清晰,维护性大大提升。 |
到此这篇关于springboot中entity、dto、vo的通俗理解与实战案例的文章就介绍到这了,更多相关springboot entity、dto、vo内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论