从零开始掌握DAO、DTO、DO等模型对象:开发中的核心概念解析
1. 为什么需要这么多对象模型刚入行的时候我也被各种O搞晕过。DAO、DTO、DO、VO...这些看起来差不多的缩写到底有什么区别为什么不能用一个对象搞定所有事情直到有次在项目里把所有数据都用Map传递结果被同事吐槽这代码半年后你自己都看不懂才意识到对象模型的重要性。想象你搬家时的场景搬家师傅用纸箱装物品DAO物流车运输时用标准托盘DTO搬进新家后要拆箱整理DO最后把物品摆放在合适位置VO。每个环节都有最适合的容器混用会导致效率低下甚至物品损坏。代码中的对象模型也是同样的道理。2. 基础模型三剑客DAO、DTO、DO2.1 DAO数据库的专属接口DAOData Access Object就像你家的专属管家。当你想从仓库数据库取东西时不需要自己爬梯子翻货架只要告诉管家帮我拿客厅的那幅画管家会处理好所有底层操作。public interface UserDao { UserDO getById(Long id); // 按ID查询 ListUserDO listByAge(int age); // 条件查询 int insert(UserDO user); // 插入数据 int update(UserDO user); // 更新数据 }实际项目中MyBatis的Mapper接口就是典型的DAO实现。我习惯给所有DAO方法添加Transactional注解确保数据库操作的原子性。曾经有个支付系统因为漏加这个注解导致并发时出现数据错乱。2.2 DTO数据运输的集装箱DTOData Transfer Object是系统间传输数据的标准集装箱。它最大的特点就是单纯——只有属性和getter/setter没有任何业务逻辑。就像快递包裹上的面单只记录物品信息不关心运输过程。public class UserDTO { private String username; private String avatarUrl; // 只有getter/setter }在微服务架构中DTO特别重要。我们团队曾因为直接传递数据库实体导致接口变更引发连锁反应。后来强制规定所有跨服务调用必须通过DTO接口稳定性提高了70%。2.3 DO业务领域的灵魂DODomain Object是业务逻辑的核心载体。与DTO不同DO包含丰富的业务行为。比如用户修改密码场景public class UserDO { private String password; public void changePassword(String oldPwd, String newPwd) { if(!this.password.equals(hash(oldPwd))) { throw new BusinessException(旧密码错误); } this.password hash(newPwd); } }这里有个经验之谈DO的方法应该聚焦单一业务动作。曾经见过一个2000行的UserDO包含了积分、订单、地址等各种逻辑维护起来简直是噩梦。3. 展示层专用模型VO与View3.1 VO前端的数据菜单VOView Object就像为前端定制的数据套餐。后端经常需要把多个DO组合成前端需要的结构public class UserProfileVO { private UserBasicVO basic; private ListOrderSimpleVO orders; private MemberLevelVO level; }在电商项目中商品详情页的VO可能包含商品基本信息、SKU列表、促销信息、评价统计等来自不同领域的数据。我习惯用Builder模式构造复杂VOProductVO vo ProductVO.builder() .basic(productDO.toBasicVO()) .skus(skuService.listByProduct(id)) .build();3.2 ViewMVC中的页面指挥官在MVC架构中View决定页面如何展示数据。以Thymeleaf模板为例div th:if${user.vip} img src/assets/vip-badge.png /div实际开发中容易犯的错误是把业务逻辑写在View里。记得有次排查bug发现JSP里竟然有金额计算逻辑这种反模式会导致维护困难。4. 其他常见模型解析4.1 POJO与PO最基础的Java对象POJO就是普通的Java对象比如public class User { private String name; // getter/setter }而POPersistent Object特指与数据库表映射的对象。使用MyBatis时常见的场景resultMap iduserMap typeUserPO id columnid propertyid/ result columnuser_name propertyname/ /resultMap4.2 BO与AO业务逻辑的组织者BOBusiness Object是业务流程的协调者。比如下单流程public class OrderBO { public OrderResult createOrder(OrderRequest request) { // 验证库存 // 计算价格 // 创建订单 // 发送通知 } }AOApplication Object更像是跨层数据传输的通用载体。在RPC调用中经常见到public class RpcResultT { private boolean success; private T data; private String errorMsg; }5. 实际项目中的模型转换模型转换是避免不了的但要注意转换时机。推荐在架构边界处进行转换DAO层返回DO给Service层Service层将DO转换为DTO给ControllerController将DTO转换为VO给前端使用MapStruct可以简化转换代码Mapper public interface UserConverter { UserConverter INSTANCE Mappers.getMapper(UserConverter.class); UserDTO doToDto(UserDO user); UserVO dtoToVo(UserDTO dto); }曾经有个项目没有规范转换流程导致一个请求中反复转换了7次对象性能下降了40%。后来我们制定了严格的转换规范禁止在循环内转换对象大列表采用批量转换敏感字段在最早可能的环节过滤掉6. 如何设计好的对象模型经过多个项目的实践我总结了这些经验明确职责边界DAO只管数据库访问DTO只管数据传输DO承载业务逻辑保持immutableDTO/VO尽量设计成不可变对象final字段构造器注入版本兼容对外暴露的DTO要考虑向后兼容新增字段不要影响老接口分层校验DTO做基础校验非空、格式DO做业务校验状态、权限性能考量大对象要懒加载关联数据考虑用ID代替完整对象引用在最近的一个微服务项目中我们通过规范对象模型设计使接口平均响应时间降低了30%而且代码的可读性大幅提升。新同事上手时只要看对象模型的定义就能理解业务场景。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2489946.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!