对于DTO和DO的命名规则 , 请参见:
https://www.cnblogs.com/qixuejia/p/10789612.html
DTO与DO的应用从上一节的例子中 , 细心的读者可能会发现问题:既然getUser *** 返回的UserInfo不应该包含password , 那么就不应该存在password这个属性定义
但如果同时有一个createUser的 *** , 传入的UserInfo需要包含用户的password , 怎么办?
在设计层面 , 展示层向服务层传递的DTO与服务层返回给展示层的DTO在概念上是不同的 , 但在实现层面 , 我们通常很少会这样做(定义两个UserInfo , 甚至更多) , 因为这样做并不见得很明智
我们完全可以设计一个完全兼容的DTO , 在服务层接收数据的时候 , 不该由展示层设置的属性(如订单的总价应该由其单价、数量、折扣等决定) , 无论展示层是否设置 , 服务层都一概忽略 , 而在服务层返回数据时 , 不该返回的数据(如用户密码) , 就不设置对应的属性 。
对于DO来说 , 还有一点需要说明:为什么不在服务层中直接返回DO呢?这样可以省去DTO的编码和转换工作 , 原因如下:
- 两者在本质上的区别可能导致彼此并不一一对应 , 一个DTO可能对应多个DO , 反之亦然 , 甚至两者存在多对多的关系 。
- DO具有一些不应该让展示层知道的数据
- DO具有业务 *** , 如果直接把DO传递给展示层 , 展示层的代码就可以绕过服务层直接调用它不应该访问的操作 , 对于基于AOP拦截服务层来进行访问控制的机制来说 , 这问题尤为突出 , 而在展示层调用DO的业务 *** 也会因为事务的问题 , 让事务难以控制 。
- 对于某些ORM框架(如Hibernate)来说 , 通常会使用“延迟加载”技术 , 如果直接把DO暴露给展示层 , 对于大部分情况 , 展示层不在事务范围之内(Open session in view在大部分情况下不是一种值得推崇的设计) , 如果其尝试在Session关闭的情况下获取一个未加载的关联对象 , 会出现运行时异常(对于Hibernate来说 , 就是LazyInitiliaztionException)
- 从设计层面来说 , 展示层依赖于服务层 , 服务层依赖于领域层 , 如果把DO暴露出去 , 就会导致展示层直接依赖于领域层 , 这虽然依然是单向依赖 , 但这种跨层依赖会导致不必要的耦合 。
举个例子来说明:如果User会关联若干个其他实体(例如Address、Account、Region等) , 那么getUser()返回的UserInfo , 是否就需要把其关联的对象的DTO都一并返回呢?
如果这样的话 , 必然导致数据传输量的大增 , 对于分布式应用来说 , 由于涉及数据在网络上的传输、序列化和反序列化 , 这种设计更不可接受 。
如果getUser除了要返回User的基本信息外 , 还需要返回一个AccountId、AccountName、RegionId、RegionName , 那么 , 请把这些属性定义到UserInfo中 , 把一个“立体”的对象树“压扁”成一个“扁平的二维对象”
笔者目前参与的项目是一个分布式系统 , 该系统不管三七二十一 , 把一个对象的所有关联对象都转换为相同结构的DTO对象树并返回 , 导致性能非常的慢 。
推荐阅读
- 三炮是什么意思?三炮是什么意思喝酒
- 有没有人分享一下现编的故事?
- 金砖国家 金砖四国 金砖四国为什么叫金砖
- 近日澳大利亚蝙蝠成灾了,像生化武器满身病毒的蝙蝠有天敌吗?
- 有文化底蕴的幼儿园名字 幼儿园名字大全独特
- 祝同学们学业进步的句子以梦为马 祝同学们学业进步的句子
- 宋朝时期的娼妓繁荣程度更胜于唐,是什么促进了宋代青楼的发展?
- 羊是怎么叫的
- 如果把吉林队的琼斯给广东,CBA是否会迎来大结局?