DO与PO的区别DO和PO在绝大部分情况下是一一对应的 , PO是只含有get/set *** 的POJO , 但某些场景还是能反映出两者在概念上存在本质的区别:
- DO在某些场景下不需要进行显式的持久化 , 例如利用策略模式设计的商品折扣策略 , 会衍生出折扣策略的接口和不同折扣策略实现类 , 这些折扣策略实现类可以算是DO , 但它们只驻留在静态内存 , 不需要持久化到持久层 , 因此 , 这类DO是不存在对应的PO的 。
- 同样的道理 , 某些场景下 , PO也没有对应的DO
- 例如老师Teacher和学生Student存在多对多的关系 , 在关系数据库中 , 这种关系需要表现为一个中间表 , 也就对应有一个TeacherAndStudentPO的PO
- 但这个PO在业务领域没有任何现实的意义 , 它完全不能与任何DO对应上 。
- 这里要特别声明 , 并不是所有多对多关系都没有业务含义 , 这跟具体业务场景有关
- 例如:两个PO之间的关系会影响具体业务 , 并且这种关系存在多种类型 , 那么这种多对多关系也应该表现为一个DO , 又如:“角色”与“资源”之间存在多对多关系 , 而这种关系很明显会表现为一个DO——“权限” 。
- 某些情况下 , 为了某种持久化策略或者性能的考虑 , 一个PO可能对应多个DO , 反之亦然 。
- 例如客户Customer有其联系信息Contacts , 这里是两个一对一关系的DO , 但可能出于性能的考虑(极端情况 , 权作举例) , 为了减少数据库的连接查询操作 , 把Customer和Contacts两个DO数据合并到一张数据表中 。
- 反过来 , 如果一本图书Book , 有一个属性是封面cover , 但该属性是一副图片的二进制数据 , 而某些查询操作不希望把cover一并加载 , 从而减轻磁盘IO开销 , 同时假设ORM框架不支持属性级别的延迟加载 , 那么就需要考虑把cover独立到一张数据表中去 , 这样就形成一个DO对应对个PO的情况 。
- PO的某些属性值对于DO没有任何意义 , 这些属性值可能是为了解决某些持久化策略而存在的数据 , 例如为了实现“乐观锁” , PO存在一个version的属性 , 这个version对于DO来说是没有任何业务意义的 , 它不应该在DO中存在 。同理 , DO中也可能存在不需要持久化的属性 。
- 由于ORM框架的功能非常强大而大行其道 , 而且JavaEE也推出了JPA规范 , 现在的业务应用开发 , 基本上不需要区分DO与PO , PO完全可以通过JPA , Hibernate Annotations/hbm隐藏在DO之中 。虽然如此 , 但有些问题我们还必须注意:
- 对于DO中不需要持久化的属性 , 需要通过ORM显式的声明 , 如:在JPA中 , [email protected]
- 对于PO中为了某种持久化策略而存在的属性 , 例如version , 由于DO、PO合并了 , 必须在DO中声明 , 但由于这个属性对DO是没有任何业务意义的 , 需要让该属性对外隐藏起来
- 最常见的做法是把该属性的get/set *** 私有化 , 甚至不提供get/set ***
- 但对于Hibernate来说 , 这需要特别注意 , 由于Hibernate从数据库读取数据转换为DO时 , 是利用反射机制先调用DO的空参数构造函数构造DO实例 , 然后再利用JavaBean的规范反射出set *** 来为每个属性设值 , 如果不显式声明set *** , 或把set *** 设置为private , 都会导致Hibernate无法初始化DO , 从而出现运行时异常 , 可行的做法是把属性的set *** 设置为protected 。
推荐阅读
- 三炮是什么意思?三炮是什么意思喝酒
- 有没有人分享一下现编的故事?
- 金砖国家 金砖四国 金砖四国为什么叫金砖
- 近日澳大利亚蝙蝠成灾了,像生化武器满身病毒的蝙蝠有天敌吗?
- 有文化底蕴的幼儿园名字 幼儿园名字大全独特
- 祝同学们学业进步的句子以梦为马 祝同学们学业进步的句子
- 宋朝时期的娼妓繁荣程度更胜于唐,是什么促进了宋代青楼的发展?
- 羊是怎么叫的
- 如果把吉林队的琼斯给广东,CBA是否会迎来大结局?