PO/ENTITY/VO/DTO/POJO/BO以及JavaBean介绍

无论是在实际开发过程中,还是阅读各种技术书籍,PO/VO/DTO/POJO以及JavaBean都是相对的高频词汇,因此有必要对它们各自的含义以及相互间的区别有一个清晰的认识和理解。

PO / ENTITY

Persistent Object 持久对象

1 .有时也被称为Data对象,对应数据库中的entity,可以简单认为一个PO对应数据库中的一条记录。

2 .PO中不应该包含任何对数据库的操作。

DO

Domain Object 领域对象

从现实世界中抽象出来的有形或无形的业务实体。

TO

Transfer Object 数据传输对象

在应用程序不同 tie( 关系 ) 之间传输的对象

DTO

Data Transfer Object 数据传输对象

这个概念来源于J2EE的设计模式,原来的目的是为了EJB的分布式应用提供粗粒度的数据实体,以减少分布式调用的次数,从而提高分布式调用的性能和降低网络负载,但在这里,我泛指用于展示层与服务层之间的数据传输对象。

1 .用在需要跨进程或远程传输时,它不应该包含业务逻辑。

2 .比如一张表有100个字段,那么对应的PO就有100个属性(大多数情况下,DTO内的数据来自多个表)。但view层只需显示10个字段,没有必要把整个PO对象传递到client,这时我们就可以用只有这10个属性的DTO来传输数据到client,这样也不会暴露server端表结构。到达客户端以后,如果用这个对象来对应界面显示,那此时它的身份就转为VO。

VO

value object 值对象 / view object 表现对象

视图对象,用于展示层,它的作用是把某个指定页面(或组件)的所有数据封装起来。

1 .通常用于表现层与控制层的数据传递,和PO一样也是仅仅包含数据而已。应用:对应页面显示(web页面/swt、swing界面)的数据对象。

2 .是抽象出的业务对象,可以和表对应,也可以不,这根据业务的需要。

3 .用 new 关键字创建,由 GC 回收的。

注 :在struts中,用ActionForm做VO,需要做一个转换,因为PO是面向对象的,而ActionForm是和view对应的,要将几个PO要显示的属性合成一个ActionForm,可以使用BeanUtils的copy方法。

BO

business object 业务对象

业务对象主要作用是把业务逻辑封装为一个对象。这个对象可以包括一个或多个其它的对象。

比如一个简历,有教育经历、工作经历、社会关系等等。我们可以把教育经历对应一个PO,工作经历对应一个PO,社会关系对应一个PO。建立一个对应简历的BO对象处理简历,每个BO包含这些PO。这样处理业务逻辑时,我们就可以针对BO去处理。

封装业务逻辑为一个对象(可以包括多个PO,通常需要将BO转化成PO,才能进行数据的持久化,反之,从DB中得到的PO,需要转化成BO才能在业务层使用)。

关于BO主要有三种概念

1 、只包含业务对象的属性;

2 、只包含业务方法;

3 、两者都包含。

在实际使用中,认为哪一种概念正确并不重要,关键是实际应用中适合自己项目的需要。

POJO

plain ordinary java object 无规则简单java对象

一个中间对象,可以转化为PO、DTO、VO。

1 .POJO持久化之后==〉PO

(在运行期,由Hibernate中的cglib动态把POJO转换为PO,PO相对于POJO会增加一些用来管理数据库entity状态的属性和方法。PO对于programmer来说完全透明,由于是运行期生成PO,所以可以支持增量编译,增量调试。)

2 .POJO传输过程中==〉DTO

3 .POJO用作表示层==〉VO

PO 和VO都应该属于它。在实际开发中,可能只有PO(Entity)和VO,在需要DTO的时候VO充当了DTO的角色,如果VO的字段A在数据库中不存在(即不需要从数据库中取值),则查询的时候可以随便赋一个值给字段A。

JavaBean

一种JAVA语言写成的可重用组件。它的方法命名,构造及行为必须符合特定的约定:

1、这个类必须有一个公共的缺省构造函数。

2、这个类的属性使用getter和setter来访问,其他方法遵从标准命名规范。

3、这个类应是可序列化的。

因为这些要求主要是靠约定而不是靠实现接口,所以许多开发者把JavaBean看作遵从特定命名约定的POJO。

简而言之,当一个Pojo可序列化,有一个无参的构造函数,使用getter和setter方法来访问属性时,他就是一个JavaBean

DAO

data access object数据访问对象

1 .主要用来封装对DB的访问(CRUD操作)。

2 .通过接收Business层的数据,把POJO持久化为PO。

简易的关系图:

这里写图片描述


Model与Entity

java 后台开发中model与entity(实体类)的区别

model的字段要多于entity的字段,并且model的字段属性可以与entity不一致,model是用于前端页面数据展示的,而entity则是与数据库进行交互做存储用途。

举个例子:
比如在存储时间的类型时,数据库中存的是datetime类型,entity 获取时的类型是 Date() 类型,Date 型的数据在前端展示的时候必须进行类型转换(转为String类型),在前端的进行类型转换则十分的麻烦,转换成功了代码也显得十分的臃肿,所以将entity类型转换后,存储到对应的model中,在后台做类型转换,然后将model传到前端显示时,前端的就十分的干净。同时也可以添加字段,作为数据中转。

​ 具体转换思路待续!

实践

一、

VO对应于页面上需要显示的数据,ENTITY对应于数据库中存储的数据,DTO对应于除二者之外需要进行传递的数据。

二、

1、[controller] controller是从用户接受和发送数据的地方。因此 controller 中返回结果中的数据类型为 VO 类型。

2、[dao] 那么, mybatismapper 中写的 sql 语句,如 select 等的返回结果是什么呢? 可以是 entity,可以是DTO。从一张表中查询部分或多表联合查询,就可以返回DTO

整个 mapper.xmlDAO 对应,其中每个sql语句的返回类型可以是 intListentityDTO 等。

1
2
3
4
5
@RequestMapping(path = "/list", method = RequestMethod.POST)
public Res<VO> yourmethoed(){
//<DTO> = service()...
//DTO转VO,return VO
}

三、

当你业务足够简单时,一个POJO 也完全当做PO DTO VO BO 看,下面是例子:
比如有个用户类 只有 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 下 不但有用户本身的一些属性,还包含了用户设置 和用户信息这两个类。

其实具体要分到什么程度还是要看项目,很多时候他们其实会没什么区别。