哪怕字段一模一样,也要用 VO
VO 只关心「展示」
一致只是巧合,不是约定
一张表 = 一个 DO
数据库表结构映射
ORM 操作唯一入口
@TableName("user_integral") public class UserIntegralDO {
@TableId(type = IdType.AUTO) private Long id;
private Long pntCustId;
private BigDecimal integralBalance;
private Integer isDeleted;
private LocalDateTime createTime; }
✅ 允许
MyBatis-Plus 注解
Getter / Setter
Lombok(@Data)
❌ 禁止
@NotNull / @Valid
前端展示字段
构造复杂业务逻辑
引用 DTO / VO
一个接口 ≈ 一个 DTO
接收请求参数
参数校验
查询条件封装
public class UserIntegralQueryDTO {
@NotNull(message = "客户ID不能为空") private Long pntCustId;
private Integer operateType;
private LocalDateTime beginOperateTime; private LocalDateTime endOperateTime;
// 分页参数(推荐统一继承) private Integer pageNum = 1; private Integer pageSize = 10;
public Page toPage() { return new Page(pageNum, pageSize); } }
✅ 允许
@NotNull、@Valid
默认值
分页辅助方法
❌ 禁止
@TableName
@TableField
任何数据库字段强绑定
Service / Mapper 调用
VO = 前端真正关心的数据结构
聚合多个 DO
返回给前端
屏蔽数据库细节
public class UserIntegralVo {
private UserIntegralDO userIntegral;
private Page<UserIntegralDetailDO> userIntegralDetailPage;
private BigDecimal waitSettleIntegral;
private IntegralProductConfigDO integralProductConfig; }
注意:
这里返回 DO 是「业务妥协」,不是推荐做法
理想情况应拆成 VO
public class UserIntegralVO {
private BigDecimal integralBalance;
private BigDecimal waitSettleIntegral;
private List<UserIntegralDetailVO> details; }
✅ 允许
字段重命名(可读性)
BigDecimal / String
枚举翻译后的值
❌ 禁止
@TableField
ORM 注解
Mapper 调用
Service 是 DTO / DO / VO 的“交通警察”
public UserIntegralVo selectUserIntegral2(UserIntegralQueryDTO dto) {
UserIntegralDO userIntegralDO = iUserIntegralService.getOne( Wrappers.<UserIntegralDO>lambdaQuery() .eq(dto.getPntCustId() != null, UserIntegralDO::getPntCustId, dto.getPntCustId()) .eq(UserIntegralDO::getIsDeleted, 0) );
if (userIntegralDO == null) { return null; }
UserIntegralVo vo = new UserIntegralVo(); vo.setUserIntegralDO(userIntegralDO); vo.setWaitSettleIntegral(...);
return vo; }
DTO 管进,DO 管库,VO 管出;
DTO 不碰表,VO 不查库,DO 不接参;
Wrapper 永远三参数,Service 负责翻译。