在本教程中,我们将学习什么是数据传输对象(DTO)、值对象(VO)、普通的 Java 对象(POJO)和 JavaBeans。我们将了解它们之间的区别,并理解应该使用哪种类型以及何时使用。
POJO,也称为 Java 原生类对象,是一种普通的 Java 对象,不引用任何特定的框架。它是一个用于指代简单、轻量级 Java 对象的术语。
POJO 不使用任何属性和方法的命名约定。
让我们定义一个基本的 EmployeePOJO 对象,它具有三个属性:
public class EmployeePOJO {
private String firstName;
private String lastName;
private LocalDate startDate;
public EmployeePOJO(String firstName, String lastName, LocalDate startDate) {
this.firstName = firstName;
this.lastName = lastName;
this.startDate = startDate;
}
public String name() {
return this.firstName + " " + this.lastName;
}
public LocalDate getStart() {
return this.startDate;
}
}
正如我们所看到的,上面的 Java 对象定义了表示员工的结构,不依赖于任何框架。
JavaBeans 与 POJO 类似,但有一些严格的规则需要遵循。
规则规定它应该是可序列化的,具有空构造函数,并允许使用遵循 getX() 和 setX() 约定的方法访问变量。
由于 JavaBeans 本质上是 POJO,让我们通过实现必要的 bean 规则将 EmployeePOJO 转换为 JavaBeans:
public class EmployeeBean implements Serializable {
private static final long serialVersionUID = -3760445487636086034L;
private String firstName;
private String lastName;
private LocalDate startDate;
public EmployeeBean() {
}
public EmployeeBean(String firstName, String lastName, LocalDate startDate) {
this.firstName = firstName;
this.lastName = lastName;
this.startDate = startDate;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
// additional getters and setters
}
在这里,为了将 POJO 转换为 JavaBeans,我们实现了 Serializable 接口,将属性标记为 private,并使用 getter/setter 方法访问属性。
DTO,也称为数据传输对象,封装了值,以在进程或网络之间传递数据。
这有助于减少调用的方法数量。通过在单个调用中包含多个参数或值,我们减少了远程操作中的网络开销。
该模式的另一个优点是序列化逻辑的封装。它允许程序以特定格式存储和传输数据。
DTO 没有任何显式行为。它基本上通过将域模型与表示层解耦,有助于使代码松耦合。
DTO 具有没有任何业务逻辑的扁平结构。它们使用与 POJO 相同的格式。DTO 只包含与序列化或解析相关的存储、访问器和方法。
DTO 基本上映射到域模型,因此将数据发送到方法或服务器。
让我们创建 EmployeeDTO,它将所有创建员工所需的详细信息分组。我们将在单个请求中向服务器发送这些数据,以优化与 API 的交互:
public class EmployeeDTO {
private String firstName;
private String lastName;
private LocalDate startDate;
// standard getters and setters
}
上述 DTO 与不同的服务进行交互并处理数据流。这个 DTO 模式可以在任何服务中使用,没有任何框架的限制。
VO,也称为值对象,是一种特殊类型的对象,可以保存值,例如 java.lang.Integer 和 java.lang.Long。
VO 应该始终覆盖 equals() 和 hashCode() 方法。VO 通常封装小型对象,例如数字、日期、字符串等等。它们遵循值语义,即它们直接更改对象的值并传递副本而不是引用。
将值对象设置为不可变是一个好习惯。值的更改只能通过创建一个新对象而不是更新旧对象本身来发生。这有助于理解两个创建相等的值对象的隐式契约应该保持相等。
让我们定义 EmployeeVO 并覆盖 equals() 和 hashCode() 方法:
public final class EmployeeVO {
private final String firstName;
private final String lastName;
private final LocalDate startDate;
public EmployeeVO(String firstName, String lastName, LocalDate startDate) {
this.firstName = firstName;
this.lastName = lastName;
this.startDate = startDate;
}
// Getters
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
EmployeeVO emp = (EmployeeVO) obj;
return Objects.equals(firstName, emp.firstName)
&& Objects.equals(lastName, emp.lastName)
&& Objects.equals(startDate, emp.startDate);
}
@Override
public int hashCode() {
return Objects.hash(firstName, lastName, startDate);
}
}
在本文中,我们看到了 POJO、JavaBeans、DTO 和值对象的定义。我们还看到了一些框架和库如何利用 JavaBean 命名约定,以及如何将 POJO 转换为 JavaBean。我们还看到了 DTO 模式和值对象以及它们在不同场景下的使用。
接下来,Java 14 记录通过抽象 getter、setter、equals 和 hashcode 增强了可读性,并提供了开箱即用的不可变性。您可以在我们的文章中阅读更多信息。
像往常一样,这些示例的代码可在 GitHub 上获得。
原文地址:https://www.baeldung.com/java-pojo-javabeans-dto-vo
拓展讲解:
在 Java 中, POJO、JavaBeans、DTO 和 VO 都是常见的用于数据传输和封装的模式,它们之间的主要区别如下:
POJO(Plain Old Java Object,简单的 Java 对象):它是一个普通的 Java 对象,没有任何特殊的限制和要求,一般用于表示领域模型中的数据实体,如职工、部门、订单等等。它没有实现任何特定的接口或继承任何特定的类,也不需要遵循任何约定或规范。
JavaBeans:JavaBeans 是一种符合特定规范的 POJO,它必须满足一定的条件,例如具有无参构造函数、属性用 get/set 方法封装、可序列化等等。JavaBeans 一般用于在图形界面中显示或操作数据。
DTO(Data Transfer Object,数据传输对象):DTO 是一种用于数据传输的对象,它一般包含一些属性,用于在应用程序的不同层之间传输数据,例如从服务层传递数据到表现层。DTO 通常包含一些与领域模型无关的属性,用于传递数据而不是表示实体。
VO(Value Object,值对象):VO 是一种用于表示领域模型中的值的对象,它通常是不可变的,一旦创建就不会改变。VO 一般包含一些属性,用于表示某个特定的值,例如货币、日期、地址等等。VO 可以用于在应用程序的不同层之间传递值,但一般不包含与业务逻辑相关的方法。
总之,这些模式都是用于封装和传输数据的对象,但它们的具体用途和特点略有不同。选择哪种模式取决于具体的应用场景和需求。