当前位置: 首页 > article >正文

SpringBoot分层概念澄清 DTO、BO、VO

spring boot项目中: DTO就是前端到控制层 BO就是数据库到服务层 VO就是服务层到前端 这样理解是否正确在Spring Boot项目中关于DTO、BO和VO的划分确实存在一些常见约定但你的理解中有些地方需要进一步澄清。下面是对这些概念在典型分层架构中的解释1. DTOData Transfer Object数据传输对象你的理解前端到控制层更准确的定位DTO 通常用于不同层之间的数据传输尤其是控制层Controller与服务层Service之间也可以用于服务层与外部接口之间。作用接收前端请求参数如JSON → DTO返回给前端的响应数据如DTO → JSON避免直接暴露实体Entity结构同时可以聚合多个字段或进行数据校验方向双向前端 → 控制层控制层 → 前端2. BOBusiness Object业务对象你的理解数据库到服务层更准确的定位BO 主要封装业务逻辑在服务层内部使用。它通常由一个或多个实体Entity组合而成也可能包含一些业务状态或方法用于处理复杂的业务规则。注意数据库到服务层的直接映射通常由实体Entity完成如JPA的Entity而不是BO。BO是服务层对实体进行业务加工后的对象。方向仅在服务层内部流转3. VOView Object视图对象你的理解服务层到前端更准确的定位VO 是专门为前端视图定制的数据对象由服务层返回给控制层再由控制层序列化后发送给前端。它通常包含前端需要展示的字段可能经过格式化、聚合或裁剪。与DTO的关系在很多项目中返回给前端的对象也常被称为DTO但VO更强调“视图展示”的语义而DTO更强调“数据传输”。如果严格区分VO可以看作是服务于前端视图的DTO。方向服务层 → 控制层 → 前端修正后的理解前端 → 控制层通常用DTO接收请求参数控制层 → 服务层可使用DTO传递参数服务层内部处理时可能转换为BO或直接操作Entity服务层内部使用BO处理业务逻辑可能组合多个Entity服务层 → 控制层返回VO或 DTO给前端展示数据库 ↔ 服务层通过Entity进行ORM映射Entity 代表数据持久化对象总结你的基本方向是对的但术语的精确职责和层次需要更清晰DTO是跨层传输的通用载体常用于前端与后端、服务层之间的交互。BO是服务层的业务抽象不直接与数据库或前端耦合。VO是专为前端视图定制的对象。Entity才是数据库到服务层的直接映射。在实际项目中团队可以根据自身约定灵活命名但保持分层清晰和数据隔离是关键。那如果使用MyBatis多表联合查询出来的数据集resultType不是用BO吗在 MyBatis 中进行多表联合查询时返回的结果集通常不应该直接定义为 BO业务对象而更常见的是使用DTO数据传输对象或专门为该查询创建的POJO例如命名为XxxQueryResult。下面详细解释原因和最佳实践。1. 为什么多表查询结果不适合直接用 BOBO 的本质业务对象BO是服务层内部对业务逻辑的封装它可能包含多个实体Entity的组合甚至包含业务方法。BO 的设计目的是为业务服务而不是为数据库查询服务。MyBatis 查询结果的本质多表联合查询返回的是数据的投影来自不同表的字段组合通常只是原始数据的简单聚合不包含业务行为。它应该是一个轻量的数据容器直接映射为 POJO。2. 应该使用什么对象DTO数据传输对象这是最常用的选择。DTO 用于在不同层次之间传输数据比如从数据库层MyBatis到服务层或者从服务层到控制层。多表查询的结果正是数据在不同表之间的传输用 DTO 非常合适。自定义查询结果对象你也可以为每个特定的多表查询定义一个 POJO放在类似dto或vo包下命名为XxxDetailDTO、XxxQueryResult等。这其实也是 DTO 的一种形式。3. 示例说明假设有user表和order表需要查询用户及其最近订单的信息sqlSELECT u.id, u.name, o.order_no, o.amount FROM user u LEFT JOIN order o ON u.id o.user_id WHERE ...对应的 MyBatis 结果映射javapublic class UserOrderDTO { private Long id; // 来自 user 表 private String name; // 来自 user 表 private String orderNo; // 来自 order 表 private BigDecimal amount; // 来自 order 表 // getters/setters }然后在 Mapper 中xmlselect idselectUserWithOrder resultTypecom.example.dto.UserOrderDTO ... /select这里的UserOrderDTO就是专为这个查询设计的 DTO它不属于任何实体Entity也不包含业务逻辑只负责承载查询结果。4. 与 BO 的关系如果服务层需要基于这个查询结果执行复杂的业务逻辑你可以在服务层将 DTO 转换为 BO让 BO 继续后续的业务处理。但 MyBatis 直接返回的仍是 DTO。例如java// Service 层 ListUserOrderDTO dtoList userMapper.selectUserWithOrder(...); ListUserOrderBO boList dtoList.stream().map(dto - { UserOrderBO bo new UserOrderBO(); // 可能补充其他业务字段或调用业务方法 bo.setUser(User.builder().id(dto.getId()).name(dto.getName()).build()); bo.setOrder(Order.builder().orderNo(dto.getOrderNo()).amount(dto.getAmount()).build()); return bo; }).collect(Collectors.toList());5. 结论MyBatis 多表查询的结果类型→DTO 或自定义查询结果对象放在 dto 包下。BO是服务层的业务抽象由服务层根据 DTO 和实体Entity组装而成不应该由 MyBatis 直接返回。这样做可以保持各层职责清晰数据库层只负责数据获取服务层负责业务组装控制层负责视图适配。代码示例服务层Entity、BO、DTOsrc/main/java/com/weiyu/service/WorkflowService.java/** * 查询办理信息列表 */ public ListAuditInfoDTO queryAuditInfoList(Integer workflowInstanceId) { ListAuditInfoJoinQueryDTO queryDTOs workflowMapper.selectAuditInfoListByJoinQuery(workflowInstanceId); // Entity - BO预加载所有相关数据避免每次遍历都查询数据库 ActivityInstanceAuditContextBO auditStateDescBO new ActivityInstanceAuditContextBO(); ListActivityInstance activityInstances getActivityInstancesByWorkflowInstanceId(workflowInstanceId); ListAuditInfo auditInfos getAuditInfosByWorkflowInstanceId(workflowInstanceId); ListAuditLog auditLogs getAuditLogsByWorkflowInstanceId(workflowInstanceId); auditStateDescBO.setActivityInstances(activityInstances); auditStateDescBO.setAuditInfos(auditInfos); auditStateDescBO.setAuditLogs(auditLogs); ListAuditInfoDTO auditInfoDTOs new ArrayList(); for (AuditInfoJoinQueryDTO queryDTO : queryDTOs) { AuditInfoDTO auditInfoDTO new AuditInfoDTO(); BeanUtils.copyProperties(queryDTO, auditInfoDTO); // 计算办理状态 String auditStateDesc getActivityInstanceAuditStateDesc( auditStateDescBO, queryDTO.activityId(), queryDTO.auditor() ); auditInfoDTO.setAuditStateDesc(auditStateDesc); auditInfoDTOs.add(auditInfoDTO); } return auditInfoDTOs; }控制层DTO、VOsrc/main/java/com/weiyu/controller/WorkflowController.java/** * 查询办理信息列表 * * param workflowInstanceId 流程实例id * return {link Result}lt;{link List}lt;{link AuditInfoVO}gt;gt; */ GetMapping(/audit-info-list/{workflowInstanceId}) public ResultListAuditInfoVO queryAuditInfoList(PathVariable Min(1) Integer workflowInstanceId) { String endpoint /workflow/audit-info-list/; String method queryAuditInfoList; log.info(【工作流程】查询办理信息列表{}{}{}, endpoint, workflowInstanceId, method); ListAuditInfoDTO auditInfoDTOs workflowService.queryAuditInfoList(workflowInstanceId); // DTO - VO ListAuditInfoVO auditInfoVOs auditInfoDTOs.stream() .map(dto - { AuditInfoVO vo new AuditInfoVO(); BeanUtils.copyProperties(dto, vo); return vo; }) .toList(); return Result.success(auditInfoVOs); }

相关文章:

SpringBoot分层概念澄清 DTO、BO、VO

spring boot项目中: DTO就是前端到控制层 BO就是数据库到服务层 VO就是服务层到前端这样理解是否正确?在Spring Boot项目中,关于DTO、BO和VO的划分确实存在一些常见约定,但你的理解中有些地方需要进一步澄清。下面是对这些概念在典型分层架构…...

计算机毕业设计springboot汽车租赁系统 SpringBoot框架下智能车辆分时租赁与调度服务平台 基于Java Web的共享汽车在线预约与运维管理系统

计算机毕业设计springboot汽车租赁系统m9112h75(配套有源码 程序 mysql数据库 论文) 本套源码可以在文本联xi,先看具体系统功能演示视频领取,可分享源码参考。随着居民出行需求的多元化与共享经济的蓬勃发展,汽车租赁行业正从传统…...

【effective C++】条款四十四:将与参数无关的代码抽离 templates

文章目录Effective C 条款44:将与参数无关的代码抽离templates核心思想:对抗"代码膨胀"规则详解与示例规则1:不与造成膨胀的参数相依规则2:处理非类型参数造成的膨胀规则3:处理类型参数造成的膨胀优化带来的…...

【第二周】论文精读:REPLUG: Retrieval-Augmented Black-Box Language Models

前言:随着大语言模型(LLM)规模的爆炸式增长(如 GPT-3, Codex 等参数量超千亿的模型),它们大多以“黑盒”API 的形式提供服务,用户无法访问其内部参数或进行微调。这使得传统的检索增强方法&…...

Mybatis进阶(一)

一、MyBatis 基于接口代理方式实现 Dao 层开发1.1 介绍采用 Mybatis 的基于接口代理方式实现 持久层 的开发,这种方式是我们后面进入企业的主流。 基于接口代理方式的开发只需要程序员编写 Mapper 接口,Mybatis 框架会为我们动态生成实现类的对象。1.2 开…...

[协程]-[详解]-launch与async

launch作用构建一个协程, 直接返回Job使用// lifecycleScope 协程作用域 lifecycleScope.launch { // 启动一个父协程delay(10000) // 模拟任务耗时 }源码解析public fun CoroutineScope.launch(context: CoroutineContext EmptyCoroutineContext,start: CoroutineStart Coro…...

开发者在 CSDN 的“修行”过程

目录 第一阶段:踩坑与复盘(底层输出) 第二阶段:CSDN 发帖逻辑(流量密码) 第三阶段:高阶答疑(建立信任) 第四阶段:涨粉与影响力变现(全链路总结…...

采购报销-发票预制及过账 增强供应商应付按订单行

1、术语发票校验:采购发票是供应商开给购货单位,据以付款、记账、纳税的依据。参照采购订单和采购入库单,按内容、价格进行发票正确性检查。一张发票过帐时,系统在供货商帐中创建一个未清项目,然后由财务会计在支付中结…...

OpenClaw 小龙虾保姆级安装教程

OpenClaw 小龙虾保姆级安装教程 小白 10 分钟搞定本地部署(Windows 系统 - 接入飞书) 引言 OpenClaw 最近实在是太火了,很多人已经做起了上门安装 500 块一次的生意,甚至有人计算下来说,靠这门手艺有机会年收入百万…...

安卓wakelock 学习

目录 1, wakelock 是什么 2,如何使用wakelock 3, 安卓系统中使用wakelock 的实例 4, 实际项目中wakelock 遇到的问题 1, wakelock 是什么 Wake Lock是一种锁的机制,只要有人拿着这个锁,系统就无法进入休眠&…...

MySQL【表的约束上】

一、表的约束在 MySQL 数据库的使用过程中,我们会发现仅靠数据类型来限制字段远远不够 —— 数据类型的约束能力单一,无法从业务逻辑层面保证数据的正确性。比如要求用户表的邮箱字段唯一、订单表的用户 ID 必须关联存在的用户,这些需求都需要…...

CPS、CPA、CPL、CPC 是什么?联盟营销 4 大模式一次读懂

如果你正在研究联盟营销,却被各种名词绕得头大——CPS、CPA、CPL、CPC 到底是什么意思?差别在哪?什么时候该用?别急,这篇文章会用最简单的语言,在一分钟内让你彻底弄懂 4 大联盟营销模式,并教你…...

(104页PPT)DG1067全面企业绩效管理(附下载方式)

篇幅所限,本文只提供部分资料内容,完整资料请看下面链接 (104页PPT)DG1067全面企业绩效管理.pptx_IT运维服务质量评价体系资源-CSDN下载 资料解读:(104 页)DG1067 全面企业绩效管理 详细资料请…...

ZBlog 爆款主题宁静致远|1.6 万 + 下载、9.89 分、6 年更新,自媒体 / 资讯站首选主题

ZBlog爆款主题「宁静致远(Quietlee)」实测推荐!累计下载16141次,评分9.89/10,自2020年上线至今持续迭代近6年,适配Z-BlogPHP 1.7.0、PHP5.6及以上版本,是个人自媒体、资讯站、小型内容平台的建站…...

IT系统全生命周期管理和运营方案(Word)

1 项目总体概述1.1 项目背景1.2 蓝图架构1.3 核心业务流程1.4 系统总体架构1.5 系统业务模型流程1.6 实施阶段划分1.7 一阶段建设目标2 一阶段解决方案2.1 系统总体架构2.2 系统总体流程2.3 软件功能设计2.3.1 统一门户(含多租户、权限、用户、角色、菜单、授权管理…...

高通跃龙QCS9100平台上工业缺陷检测实战(1): 从摄像头到端侧推理的最小闭环

💡 前言 本系列将聚焦高通跃龙QCS9100平台实施工业缺陷检测。 本文第一篇我们在该QCS9100平台将缺陷检测链路完整跑通。 你跑完这篇,应该能看到两件非常具体的东西: runs/ 里不断冒出带框的图片终端里能看到每次推理大概多少毫秒、FPS 大概…...

论文党「反内耗」神器:Paperzz 把毕业论文初稿写成「开卷答题」,4 步搞定从 0 到成稿

Paperzz-AI官网免费论文查重复率AIGC检测/开题报告/文献综述/论文初稿paperzz - 毕业论文-AIGC论文检测-AI智能降重-ai智能写作https://www.paperzz.cc/dissertation 谁懂啊家人们!写毕业论文就像在玩「地狱级闯关游戏」:对着空白文档发呆半天写不出开头…...

2026 学术写作破局:Paperzz 如何用「四步闭环法」解决毕业论文初稿难产,让你 3 天写完合格初稿

Paperzz-AI官网免费论文查重复率AIGC检测/开题报告/文献综述/论文初稿paperzz - 毕业论文-AIGC论文检测-AI智能降重-ai智能写作https://www.paperzz.cc/dissertation 引言:被毕业论文初稿困住的年轻人,正在用一种更高效的方式毕业 2026 年,国…...

从选题到成稿零焦虑:Paperzz 毕业论文初稿写作,让学术创作告别 “卡壳式内耗”

Paperzz-AI官网免费论文查重复率AIGC检测/开题报告/文献综述/论文初稿paperzz - 毕业论文-AIGC论文检测-AI智能降重-ai智能写作https://www.paperzz.cc/dissertation 在毕业论文的漫长写作路上,你是否也陷入过这样的循环:对着空白文档发呆半天写不出开头…...

TMS320F2812光伏并网逆变器设计:高效MATLAB电路仿真与DSP代码实现结合方案,含...

TMS320F2812 光伏并网逆变器设计方案,附有相关的matlab电路文件,以及DSP的程序代码,方案、仿真文件、代码三者结合使用效果好,事半功倍。 备注:赠送逆变器并联环流matlab文件,基于矢量控制的环流抑制策略和下垂控制的环…...

鸿蒙中 应用的权限(一)

本文同步发表于我的微信公众号,微信搜索 程语新视界 即可关注,每个工作日都有文章更新 一、权限管控 什么是应用权限? 系统提供一种通用权限访问方式,允许应用访问系统资源(如通讯录)和系统能力&#xff…...

LabVIEW图像处理框架核心结构示意图

labview通用图像处理框架程序源码 详情见图做图像处理的朋友应该都经历过这种尴尬:写个Demo三分钟搞定,项目一复杂就变成意大利面条代码。今天分享的这套LabVIEW通用框架,核心就三句话——状态机打底、队列传数据、插件式开发。咱们直接扒开源…...

Pyrene-PEG-NH2 氨基功能化芘荧光PEG活细胞成像与示踪探针

芘丁酸酯聚乙二醇氨基(Pyrene-PEG-NH2)是一种结合了芘(Pyrene)、聚乙二醇(PEG)和氨基(NH2)的多功能化合物。【基本信息】中文名称:芘丁酸酯-聚乙二醇-氨基;芘…...

【智慧商城 | 项目笔记】第六天

前言:智慧商城项目是关于前端的Vue2的项目,本系列文章,我讲总结我从这个项目中学到的知识点,写项目笔记。如果你也在初学Vue或想巩固Vue相关的知识,希望这系列文章可以帮助到你。 【智慧商城 | 项目笔记】第六天今日完…...

高速多串激光泵浦二极管驱动电路:可扩展、高电流、高电压、多重安全保护电路架构参考

高速多串激光泵浦二极管驱动电路,可扩展, 连续电流可达25A,支持最高电压90V; 调制频率可达10kHz 多重安全保护电路; 可单独屏蔽故障电流串; 闭环控制,带电流输出; 电路架构是基于多年…...

西门子V15及以上版本通用模拟量处理程序块:1200与1500模拟量滤波程序及报警功能

西门子1200和1500通用模拟量处理程序块,模拟量滤波程序,程序块可方便直接调用,用于过滤峰值且可以方便调用模拟量高低报警。 博图版本V15及以上。工业现场模拟量信号处理总带着点玄学,尤其是车间里那些老设备,时不时给…...

【Python一周入门】学习笔记归纳(二)六大基本类型

文章目录数字(Number)字符串String列表List元组Tuple字典Dictionary集合Set推导式列表推导式字典推导式集合推导式元组推导式(生成器推导式)数字(Number) 数字类型是客观的不可变的,分为整型,浮点型&#…...

Linux(1)的基本使用

系统每次开机默认进入字符界面[rootnode11 ~]# systemctl set-default multi-user.target系统每次开机默认进入图形界面[rootnode11 ~]# systemctl set-default graphical.targetweb界面登录(很少用)[rootnode11 ~]# systemctl enable --now cockpit.soc…...

LatentMorph:将隐式潜空间推理融入图像生成

目录 一、前言 二、 LatentMorph 论文概述 核心问题 方法:LatentMorph 实验结果 核心贡献 三、四个组件是怎么运作的,输入输出是啥 四个组件详解 1. 视觉记忆凝结器 (Memory Condensers) 2. 强化学习驱动的推理调用器 (Reason Invoker) 3.…...

2000-2024年上市公司迪博内部控制指数评分及评级数据

迪博内部控制指数简介迪博内部控制指数(DIB内部控制指数)由深圳迪博企业风险管理技术有限公司发布,是国内权威的上市公司内部控制评价体系。该指数从内部控制五要素(控制环境、风险评估、控制活动、信息与沟通、内部监督&#xff…...