POJO(plain old/ordinary java object)
普通的JavaBean,仅包含自身的属性及对应的getter、setter方法,没有继承任何类,没有实现任何接口,没有被其它框架请入的对象。
POJO特点是简单及灵活,使得其能够任意扩展,易于迁移与复用。
public class Customer{
private int id;
private String name;
//对应getter、setter方法
public String getName(){return name;}
....
}
PO(presistence object)
对象字段持有的数据需要被持久化到数据表中,参与到持久化操作的对象就被称为持久化对象。
《开发手册》中也将PO称为DO(data object),因为其自身属性通常与数据库表结构一一对应,能够将数据表中的一条记录作为一个对象处理,并转化为其它对象(如果需要的话)。
同POJO类似(多序列化版本信息),其内部包含:
- getter、setter方法;
- 与数据表结构对应的属性;
- (一般)不包含业务逻辑及数据库访问,因为数据库本身不包含这些内容;
- 在分布式存储或前端输出及远程调用时需要实现序列化,其余情况下一般不需要。
public class User implements Serializable {
//序列化版本,通过IDEA自动生成
private static final long serialiVersionUID = 1L;
private Long id;
private String username;
private String password;
//省略getter和setter方法
}
DAO(data access object)
包含:
- 对数据的访问;
- 对持久层的操作
通常结合PO来访问数据库,主要用于封装对数据的访问,并不转化为其他对象。
只在基于”事务脚本“的业务设计时包含业务逻辑,其余情况下只包含持久化封装。
public interface Dao{
int insert(User user);
User selectById(long id);
}
DTO(data transfer object)
《开发手册》规定为Service或Manager向外传输的对象,为了减少方法调用次数而在进程间传输数据的对象。
在输入方面,请求时应用在接口接收传入对象,转化为实体进行持久化,此过程中传入对象就是DTO;
在输出方面,响应时PO转换为DTO进行返回。
多个不同小DTO:PO的内容并不需要全部返回,则选取特定部分每次创建小的DTO,创建次数多,传输数据清晰;
单个大DTO:尽可能一次封装多个(可能的)PO组成DTO,减少调用次数,但难以掌握传输数据。
//继承实体类,从查询到的PO中添加属性返回给前端
public class UserDTO extends User {
//序列化版本
private static final long serialiVersionUID = 2L;
//用户标识
private String username;
public String getUsername(){return username;}
public void setUsername(String username){this.username= username;}
//添加额外属性
private HashMap<String, Object> extProperties;
public HashMap<String, Object> getExtProperties() {
return extProperties;
}
public void setExtProperties(HashMap<String, Object> extProperties) {
this.extProperties = extProperties;
}
}
Entity
实体存在于一个生命周期中,拥有自身状态。例如抽象订单一个唯一识别号作为实体,订单从创建到最后交货结束完成一整个生命周期,其状态可以变化。
实体会被给予一个唯一标识以互相区分,相对的值对象VO不需要互相区分。
与VO区别:
Entity对象的唯一标识相等,则判定两个对象相等,即使其他属性不同,同时可以修改实体状态;
VO没有标识,只当所有属性相等,才判断两个对象相等。同时不能修改,只能创建新的VO。与PO区别:
PO与数据表结构对应,通常也会赋予PO一个主键ID(同数据库),称为委派标识。例如身份证号作为实体标识唯一区分其它身份证,但在数据库中也可能会分配自增主键ID,便于存储。当VO需要持久化时也会被分配委派标识,方便查询和与外键关联;
实体标识与业务相关,委派标识与技术相关只作用于存储便利。
public class Entity{
private int id;
int getId(){return id;}
}
VO(value object)
值对象通常只作用于业务层数据传递,仅包含自身数据。
- VO通常时小而简的对象,如日期、地址等,值相同则判断两个对象相等;
- VO需易于创建,参数传递通常是值传递而非引用传递;
- VO不应被持久化,创建后只能被引用,无引用时被垃圾回收。
与Entity区别:
没有唯一标识,无生命周期,内部值不变;
与PO区别:
PO只在数据层作为存储,VO在商业逻辑层和表示层,作为概念整体。
//比如Address这样无唯一标识的就是值对象
public class Address{
private String country;
private String province;
private String city;
public Address(String country, String province, String city) {
this.country= country;
this.province= province;
this.city= city;
}
//省略equals方法
}
//调用值对象,若要修改值对象,值对象不用维护,直接创建一个全新的Address对象
//原对象直接被抛弃,而不是在原对象上进行修改
public Address changeAddress(String newCity, String newProvince, String newCity) {
return new Address(newCity, newProvince, newCity);
}
VO(view object)
此处VO通常是Web向模板渲染引擎传输的对象,《开发手册》建议把输出的显示曾对象命名为VO,也有人将这个对象命名为DTO。
同时由于许多页面需要额外数据,则会把响应的DTO封装为VO------显示层对象再显示出来。
//Controller层
public HttpResult list(@RequestBody XXParam param){
HttpResult vo=HttpResultUtils.convert(XXDTO);
return vo;
}
BO(business object)
BO就是把业务逻辑封装为一个业务对象,只包含业务对象自身的业务逻辑,不包含对外协调的逻辑,这个业务对象可以包含一个或多个其他对象。
“充血模型”指将对象的数据及行为(其本身的业务逻辑)封装在一起,service类仅用作协调称为应用服务层。这样,当业务不断演化时,只用关注BO,减轻应用层面的变化。因此BO也成为DO(domain object)的另一种说法。
public class User implements Serializable{
private String name;
private String password;
//对象自身的业务逻辑
public void changePassword(String newPassword){
this.setPassword(newPassword);
}
//省略getter、setter方法
}
QO(query object)
数据查询对象,各层用于接受上层的查询请求。当超过两个参数的查询封装,则禁止使用Map类传输。
public class MyQO {
private String param1;
private String param2;
...
}
@PostMapping("/post")
public String post(@RequestBody MyQO qo) {
......
}
MyBO bo = service.createBO(qo);//创建业务对象
bo.dosomething();
//将业务对象存储在不同的表中
MyPO po1 = service.createPO1(bo);
dao1.save(po1);
MyPO po2 = service.createPO2(bo);
dao2.save(po2);
MyPO po3 = service.createPO3(bo);
dao3.save(po3);
AO(application object)
一般用于控制层和服务层间,作为Param和VO或Param和DTO的组合,将前端查询的属性和保存的属性几乎一致的对象封装为AO。如读取用户属性传给前端,用户在前端编辑了用户属性后传回后端。
//Controller层
public HttpResult update(@RequestBody XXAO ao1){
XXAO ao2 = XXService.update(ao1);
HttpResult vo = HttpResultUtils.convert(ao2);
return vo;
}
总结
- POJO:简单Java对象,它没有任何限制和特定的约定,是一个普通的Java对象。
- DTO:数据传输对象,它是一个数据传输结构,通常用于不同进程间的数据传输,在不同层之间传递数据的对象。
- DAO:数据访问对象,是一个数据访问模式,在应用程序中它通常扮演着对数据库的访问。
- PO:持久化对象,通常指ORM(对象关系映射)中映射的数据库表对应的实体类。
- BO:业务对象,是应用程序中业务逻辑的实现。
- VO:值对象,它是一个用于存储数据的对象,通常是与UI/界面模型相关的对象。
- QO:查询对象,它主要用于定义查询条件和规则,用于接收前端传递的查询条件参数。
- ENTITY:实体对象,是一个与业务相关的对象,通常是与应用程序领域模型相关的对象。
- 习惯目录结构:
PO----bean、entiyt、model目录;
DAO----DAO、mapper、repository目录;
BO----service、manager、business、domain、model目录;
DTO----command、representation、DTO目录。
本文介绍了Java中的基础对象模型,包括POJO(简单的Java对象)、PO(持久化对象)、DAO(数据访问对象)、DTO(数据传输对象)、BO(业务对象)和VO(值对象)。它们各自的特点、用途和在软件架构中的角色得到了详细解释。

被折叠的 条评论
为什么被折叠?



