5年老鸟带你区分 VO、PO、DTO、BO、POJO、JavaBean、Entity(有图,记得收藏)

PO (Persistent Object)

PO((bean,entity等命名):持久化对象,它跟持久层(通常是关系型数据库)的数据结构形成一一对应的映射关系。
如果持久层是关系型数据库,那么,数据表中的每个字段(或若干个)就对应PO的一个(或若干个)属性。

VO(value object) 值对象 (view object)视图对象

VO(View Object):视图对象,用于展示层,它的作用是把某个指定页面(或组件)的所有数据封装起来。
主要体现在视图的对象,对于一个WEB页面将整个页面的属性封装成一个对象。然后用一个VO对象在控制层与视图层进行传输交换。
我们可以这样理解:
即 用户填写当前页面信息之后,把这些页面信息与VO对象对应起来,传到service层进行业务处理。

BO(business object) 业务对象

从业务模型的角度看 , 见 UML 元件领域模型中的领域对象。封装业务逻辑的 java 对象 , 通过调用 DAO 方法 , 结合 PO,VO 进行业务操作。 business object: 业务对象 主要作用是把业务逻辑封装为一个对象。这个对象可以包括一个或多个其它的对象。 比如一个简历,有教育经历、工作经历、社会关系等等。 我们可以把教育经历对应一个 PO ,工作经历对应一个 PO ,社会关系对应一个 PO 。 建立一个对应简历的 BO 对象处理简历,每个 BO 包含这些 PO 。 这样处理业务逻辑时,我们就可以针对 BO 去处理。

DO (Domain Object):领域对象,就是从现实世界中抽象出来的有形或无形的业务实体。

DTO(Data Transfer Object):数据传输对象

DTO:数据传输对象(Data Transfer Object)
是一种设计模式之间传输数据的软件应用系统,数据传输目标往往是数据访问对象从数据库中检索数据
数据传输对象与数据交互对象或数据访问对象之间的差异是一个以不具任何行为除了存储和检索的数据(访问和存取器)
简而言之,就是接口之间传递的数据封装
表里面有十几个字段:id,name,gender(M/F),age……
页面需要展示三个字段:name,gender(男/女),age
DTO由此产生,一是能提高数据传输的速度(减少了传输字段),二能隐藏后端表结构

在这里插入图片描述


ACTION:指的是控制层即Contoller

JavaBean 一种可重用组件

即“一次性编写,任何地方执行,任何地方重用”。满足三个条件①类必须是具体的和公共的②具有无参构造器③提供一致性设计模式的公共方法将内部域暴露成员属性。

主要用途:可以用在 功能、处理、值、数据库访问和JSP中任何可以用Java代码创造的对象。

有两种:一种是有用户界面(UI,User Interface)的JavaBean;还有一种是没有用户界面,主要负责处理事务(如数据运算,操纵数据库)的JavaBean。JSP通常访问的是后一种JavaBean。

分类:通常有Session bean,Entity bean,MessageDrivenBean三大类

——Session bean会话构件,是短暂的对象,运行在服务器上,并执行一些应用逻辑处理,它由客户端应用程序建立,其数据需要自己来管理。分为无状态和有状态两种。
——Entity bean实体构件,是持久对象,可以被其他对象调用。在建立时指定一个唯一标示的标识,并允许客户程序,根据实体bean标识来定位beans实例。多个实体可以并发访问实体bean,事务间的协调由容器来完成。
——MessageDriven Bean消息构件,是专门用来处理JMS(Java Message System)消息的规范(EIB2.0)。JMS是一种与厂商无关的API,用来访问消息收发系统,并提供了与厂商无关的访问方法,以此来访问消息收发服务。JMS客户机可以用来发送消息而不必等待回应。

JavaBean

JavaBeans:JavaBeans 从狭义来说,指的是 JavaBeans 规范也就是位于 java.beans 包中的一组 API。从广义上来说,JavaBeans 指的是 API 集合,比如 Enterprise JavaBeans。

POJO(Plain Ordinary Java Object)简单的Java对象

实际就是普通JavaBeans,是为了避免和EJB混淆所创造的简称。通指没有使用Entity Beans的普通java对象,可以把POJO作为支持业务逻辑的协助类。

POJO实质上可以理解为简单的实体类,顾名思义POJO类的作用是方便程序员使用数据库中的数据表,对于广大的程序员,可以很方便的将POJO类当做对象来进行使用,当然也是可以方便的调用其get,set方法。POJO类也给我们在struts框架中的配置带来了很大的方便。
一个POJO持久化以后就是PO
直接用它传递、传递过程中就是DTO
直接用来对应表示层就是VO

在这里插入图片描述




VO,DTO,DO,PO的联系以及区别

在这里插入图片描述

  • 用户发出请求(可能是填写表单),表单的数据在展示层被匹配为VO。

  • 展示层把VO转换为服务层对应方法所要求的DTO,传送给服务层。

  • 服务层首先根据DTO的数据构造(或重建)一个DO,调用DO的业务方法完成具体业务。

  • 服务层把DO转换为持久层对应的PO(可以使用ORM工具,也可以不用),调用持久层的持久化方法,把PO传递给它,完成持久化操作。

  • 对于一个逆向操作,如读取数据,也是用类似的方式转换和传递,略。

举例理解

下面重点说下这几个,他们都是POJOPO 持久对象,数据;
BO 业务对象,封装对象、复杂对象 ,里面可能包含多个类;
DTO 传输对象,前端调用时传输 ;
VO 表现对象,前端界面展示。

当你业务足够简单时,一个POJO 也完全当做PO BO DTO VO 看,下面是例子:比如有个用户类 只有 name 以及 phone 对于数据库层面也就两列,业务层面,传输,和前台展示时 都只有这两项。

然后说下他们区别开来的例子:
1 、还是用户类 name phone 加了个password。那么你后端的PO属性也是这3个,一般数据库里这个表有几个字段你的PO就有多少属性,但是传输到前台或者展现时,我们不应该把password 密码这种东西也一起传过去,所以他们的DTO VO 就还是 name + phone
po : name phone password
dto : name phone
vo : name phone

2、现在又加了一个 枚举的状态位 status 表示用户的一些特殊状态,前台不会直接显示,可能会根据这个状态产生后续的操作,
po : name phone password status
dto : name phone status
vo : name phone

3、接着看下BO ,一个用户下面 肯定会关联很多其他的表比如用户设置 用户信息等,那么这个BO 下 不但有用户本身的一些属性,还包含了用户设置 和用户信息这两个类。

VO和DTO的区别

大家可能会有个疑问:既然DTO是展示层与服务层之间传递数据的对象,为什么还需要一个VO呢?对!对于绝大部分的应用场景来说,DTO和VO的属性值基本是一致的,而且他们通常都是POJO,因此没必要多此一举,但不要忘记这是实现层面的思维,对于设计层面来说,概念上还是应该存在VO和DTO,因为两者有着本质的区别,DTO代表服务层需要接收的数据和返回的数据,而VO代表展示层需要显示的数据。

用一个例子来说明可能会比较容易理解:例如服务层有一个getUser的方法返回一个系统用户,其中有一个属性是gender(性别),对于服务层来说,它只从语义上定义:1-男性,2-女性,0-未指定,而对于展示层来说,它可能需要用“帅哥”代表男性,用“美女”代表女性,用“秘密”代表未指定。说到这里,可能你还会反驳,在服务层直接就返回“帅哥美女”不就行了吗?对于大部分应用来说,这不是问题,但设想一下,如果需求允许客户可以定制风格,而不同风格对于“性别”的表现方式不一样,又或者这个服务同时供多个客户端使用(不同门户),而不同的客户端对于表现层的要求有所不同,那么,问题就来了。再者,回到设计层面上分析,从职责单一原则来看,服务层只负责业务,与具体的表现形式无关,因此,它返回的DTO,不应该出现与表现形式的耦合。

理论归理论,这到底还是分析设计层面的思维,是否在实现层面必须这样做呢?一刀切的做法往往会得不偿失,下面我马上会分析应用中如何做出正确的选择。

DTO和DO的区别

首先是概念上的区别,DTO是展示层和服务层之间的数据传输对象(可以认为是两者之间的协议),而DO是对现实世界各种业务角色的抽象,这就引出了两者在数据上的区别,例如UserInfo和User(对于DTO和DO的命名规则,请参见笔者前面的一篇博文),对于一个getUser方法来说,本质上它永远不应该返回用户的密码,因此UserInfo至少比User少一个password的数据。而在领域驱动设计中,DO不是简单的POJO,它具有领域业务逻辑。

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中也可能存在不需要持久化的属性。

通过以下这些文件查看总结:
https://www.zhihu.com/question/39651928
https://www.cnblogs.com/lyjin/p/6389349.html
https://www.hollischuang.com/archives/553
http://www.blogjava.net/johnnylzb/archive/2010/05/27/321968.html

猜你喜欢

转载自blog.csdn.net/qq_41570658/article/details/120957087
今日推荐