傻傻分不清之POJO, DAO, PO, DTO, VO, BO

在Java开发中,我们都知道有这么一个O家族,其中有些平时很常用,也有一些比较少用。有的时候,我们可能会混淆其中的几个成员,今天就来整理一下,争取用最简单的方式讲清楚。

为了更形象地理解,下面的全部例子都会围绕着用户模块来展开。

POJO

POJO(Plain Ordinary Java Object),简单Java对象。很形象,就一个特点那就是简单。没有花里胡哨的其他东西,对象只有属性和getter, setter方法,没有任何业务逻辑,所以PO, DTO, VO都属于POJO。下面这个就是一个最简单的POJO。

public class User {
	private Long id;
	private String nickname;

    /* getter, setter方法 */
	...
}

DAO

DAO(Data Access Object),数据访问对象。简单来说就是提供了一组接口来访问持久化数据。说到DAO就有必要同时说一下ORM和Mapper。

一句话说一下DAO ,Mapper和ORM这三者的关系:
ORM框架实现了使用数据映射模式的DAO层(因此也称作Mapper层)与数据库交互
接下来详细地说一下。

第一, DAO是数据访问对象,这个对象有若干个接口用来访问操作持久化数据。注意是持久化数据,不仅仅是数据库,还包括XML、文件等数据持久化形式。DAO的实现多种多样,Mapper仅仅是实现方式之一。简单来说,只要你有一个对象,这个对象对外提供了一组方法来操作持久化数据,不管它底层是怎么实现的,那么它就是一个DAO。下面是一个简单的DAO的例子:

public interface UserDao {
    int createUser(User user);
    User getUserById(Long id);
}

第二, Mapper其实我认为有两种。第一种是广义上的Mapper,全称叫做数据映射模式(Data Mapper Pattern),它是一种使实体类和数据库相互映射的模式,仅仅是一种设计模式而已,它和DAO层并没有直接关联。第二种就是我们常说的Mapper层,是如Mybatis, Hibernate等ORM框架通过数据映射模式所实现的DAO层。

第三,ORM(Object Relational Mapping),对象关系映射。一听名字就知道了,就是实现了上面第二点所说的数据映射模式的数据持久层框架。Java的Mybatis和Hibernate就是两个常见的ORM框架。

通过以上三点,我们总结一下。ORM的范围最大,做的事最多,它实现了数据映射模式的DAO层来和数据库交互。ORM替你做了与数据库打交道的工作,让你不用手写代码实现DAO层,并且它所实现的DAO层由于使用了Mapper映射模式,因此通常叫它Mapper层,就是这么简单。所以我们有些时候DAO和Mapper不分也是有道理的,因为现在基本都使用这些ORM框架了,而ORM框架的特点就是用Mapper映射模式实现DAO层来和数据库交互,本来我们需要写DAO层的实现类代码,现在只需写Mapper层接口即可。接近的概念还有Table Data Gateway和Repository Pattern,这两个好像并不常用,感兴趣的可以再去了解一下。

PO

PO(Persistant Object),持久化对象。没什么好说的,最简单的POJO,属性和数据库中的表字段一一对应,没有任何数据操作和业务逻辑,仅有属性和getter, setter方法。

DTO

DTO(Data Transfer Object),数据传输对象,常常被用作前端/客户端和后端通信的入参和返回值。那么为什么需要DTO而不直接用PO代替呢,因为DTO更偏向前端或客户端,而不是后端。大部分情况下,前端/客户端所需要的数据都不会和数据库完全对应,总要对部分数据进行处理。比如前端的数据请求涉及几张不同的数据表,或是不需要全部数据,或是需要对部分数据进行加工,所以使用加工后的DTO来替代PO会更加合理。总而言之,DTO是看前端要什么,而不是看后端有什么。

VO

VO(View Object),视图对象。现在来考虑这么一种情况,在个人信息页上需要展示用户的个人信息,其中一个字段是gender性别。我们假设后端在数据库中使用tinyint(1)类型存放gender字段,在Java实体类中使用Integer类型表示gender属性,并规定0是女性,1是男性。如果后端直接将带有Integer类型的gender的DTO传输给前端,那么前端还需要再对性别做一个数值判断,再决定显示在页面上的是男还是女。如果前端和后端没有规范的接口文档来指定这个字段的含义呢?如果是客户端拿到原始数据,写死了显示的样式,而之后需求改变呢?VO做的就是这个工作,将DTO中的原始数据转化为前端所需的显示值,以便能够更加灵活地展示数据。在这个例子下,VO仅仅需要把DTO中Integer类型的gender做个判断然后修改成String类型的"男"或"女"就可以了。

BO

BO(Business Object),业务对象。BO可以算是比较抽象,比较灵活,也比较少使用的一个对象了。所谓业务对象,顾名思义,一个对象中的属性都和应用中的某个业务相关,但彼此之间却并不一定来自同一张数据表。还是用户的例子,现在我们要获取名为用户行为记录的信息(BO),其中包括了搜索记录(PO)、浏览记录(PO)和购买记录(PO)。可以看到,用户行为记录这个BO中包括了三个PO,它们由于某个特定的业务而被BO组合起来形成一个单一的实体,如下:

public class UserBehaviour {
	private Long id;
	private String nickname;
	private List<SearchingHistory> searchingHistory;
	private List<BrowsingHistory> browsingHistory;
	private List<PurchaseHistory> purchaseHistory;
	
	/* getter, setter方法 */
	...
	
	/* 业务方法 */
	...
}

可以看到在BO中还可以包含一些业务方法,这些方法可以对BO内的各个PO进行一些修改整合之类的操作。由于BO可能会包含一些业务方法,所以BO并不能算作是POJO。

那么BO和DTO又有什么区别呢,看起来也可以通过在业务层将多个PO组合而形成单一的DTO,为什么需要BO呢?这也十分困扰我,因为说实话我几乎没有使用过BO,都是在业务逻辑中进行DTO的装配。就我个人来看,BO与其说是一个业务对象,更像是一小段装配不同PO的业务逻辑,与DTO相比BO更加偏内部,处在PO和DTO之间。打个比方,现在要将搜索记录、浏览记录和购买记录装配成一个对象,不使用BO的方式是在service层中获取三个PO,然后进行某些业务相关的操作将它们和其他用户信息合并成一个DTO。而如果使用BO,以上的业务操作都可以放入BO中,让BO既实现业务计算,又装配多个PO,也就是在PO和DTO中夹了一层BO。

困扰我的地方在于,BO最后其实还是得通过DTO进行传输,而如果BO内带有部分业务逻辑,可能会和业务层产生耦合,显得不那么优雅。而如果BO内部不存在业务方法,仅有数据本身,那么又和DTO没有什么区别。这也是我较少用BO的原因。

总结

  • PO, DTO, VO都属于POJO,因为他们仅有属性和getter, setter方法。

  • BO组合了多个PO,并可能包含相关的业务计算方法

  • 当我们的需求简单时,不需要所谓的VO和BO,一个DTO就足够了。如果前端需要额外的灵活展示,那么将DTO转化成VO。如果业务逻辑复杂,在内部可以用BO组合多个PO(对这一点我目前持保留态度)。

  • DAO和以上并没有什么关系。DAO是一组数据访问接口,是应用访问数据库的必经之路。DAO可以通过数据映射实现,所以DAO层在ORM框架中也被叫作Mapper层。

P.S.

概念都是人造的,很多时候这么多名词的诞生都是由于业务的需要,不断地细分出新的层面来系统性地解决问题。我本人是相信奥卡姆剃刀原理的,如无必要,勿增实体。我认为如果事情真的复杂到需要再分层再解耦的地步,我会感觉得到。而在此之前,简单就是效率,过早的优化是万恶之源。这些分层和设计模式并不是万能的银弹,都脱离不了实际的需求,我认为当我们意识到需要它们的时候,才是我们真正需要它们的时候。

我的博客

矩阵空间

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: povobodtodaopojo都是Java编程中常用的缩写词。 - po:通常指持久化对象(Persistent Object),即数据库中的实体类,与数据库中的表一一对应。 - vo:通常指值对象(Value Object),用于封装业务逻辑中的数据,与前端展示相关。 - bo:通常指业务对象(Business Object),用于封装业务逻辑中的数据,与业务逻辑相关。 - dto:通常指数据传输对象(Data Transfer Object),用于在不同层之间传输数据,通常与前端展示无关。 - dao:通常指数据访问对象(Data Access Object),用于封装对数据库的访问,提供对数据库的增删改查操作。 - pojo:通常指普通Java对象(Plain Old Java Object),即普通的Java类,没有继承特定的接口或类,也没有实现特定的方法。 ### 回答2: po vo bo dto daopojo 是软件开发中经常使用的一些概念,用于设计和实现对象模型。下面将分别解释这些概念的含义及其在开发中的应用。 Po是指Persistant object(持久化对象),是映射到数据库表中的Java对象。Po主要用于数据交互,与数据库表结构一一对应,包含了与实体对象映射一一对应的Po实体。在开发中,如果需要进行数据库操作,则需要通过Po实体与数据库进行交互,从而实现对数据的增、删、改、查等操作。 Vo是指Value object(值对象),用于封装特定业务数据。VoPo不同的是,Vo不仅包含了与数据库映射的数据,还包含了其他一些数据字段,例如计算、统计字段等。Vo主要用于业务层的数据处理和交互,封装业务逻辑用于VO来完成,并作为业务组件的数据传递对象。 Bo是指Business object(业务对象),用于封装业务逻辑。Bo封装了特定的业务方法,实现相应的业务功能。Bo通过调用Dao进行持久化操作,或管理多个Bo进行协作完成更复杂的业务逻辑。 Dto是指Data transfer object(数据传输对象),主要用于接口层和远程调用时数据传输的封装。Dto通常包含一些传输时需要的字段,例如查询条件、分页信息等。Dto主要用于数据的传输,不包含业务逻辑。 Dao是指Data access object(数据访问对象),用于将数据访问与业务逻辑分离,Dao通过对Po对象进行CRUD操作,实现与数据库的交互。Dao在进行数据库操作时往往需要配合使用数据访问框架,例如Mybatis、Hibernate等。 Pojo是指Plain Ordinary Java object(简单Java对象),是一种纯粹的Java对象,不依赖于其他任何框架。Pojo一般用于传输数据、封装业务实体等。PojoVo比较相似,但Vo作为业务层的数据传输对象,常常包含业务逻辑,而Pojo则不会。 总之,这些概念在软件开发中的使用是相当普遍的,通过合理地使用这些概念,可以使开发者更加清晰地理解业务的实现方式,增加代码的可读性和可维护性。选择何种概念,最终需要根据具体的业务场景及功能需求决定。 ### 回答3: POVOBODTODAOPOJO都是Java中的术语。 PO指的是“持久化对象”,是用于描述持久化存储模型的Java对象,通常和数据库中的表一一对应。 在ORM(对象关系映射)框架中,PO可以将Java对象映射到数据库中的表,简化了数据的存储和持久化过程。 VO指的是“值对象”,是用于描述值的Java对象,通常是由一个或多个PO组成的。VO通常是用于在不同层之间传递数据的,例如将从数据库中查询出来的PO转化成前台可以直接使用的VO,或者将前台传入的VO转化成后台PO以进行数据的持久化存储。 BO指的是“业务对象”,是用于描述业务逻辑的Java对象,通常是由对应的多个POBODTO组成的。BO主要负责处理业务逻辑,可以看成是对PO进行多层封装后产生的对象,也可以是多个PO的组合。 DTO指的是“数据传输对象”,是用于数据传输的Java对象,通常是由一个或多个POBODTO组成的。DTO主要用于在不同模块之间传输数据,可以对数据进行封装和裁剪。 DAO指的是“数据访问对象”,是用于数据访问的Java对象,通常是负责封装数据访问层的操作,例如对数据库的增删改查等操作。DAO通过提供独立的接口,将访问数据的过程与业务分离,增强了代码的可重用性和可维护性。 POJO指的是“简单Java对象”,是一种不包含业务方法的Java对象,通常是用于封装数据的Java Bean。POJOJava EE相关性较小,可以将其看成是一种简化的Java类实现方式,适用于需要快速实现业务逻辑的场景。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值