一文讲透 Java 中 POJO, JavaBeans, DTO 和 VO 的区别

2023-05-07 20:41:31 浏览数 (2)

1、概览

在本教程中,我们将学习什么是数据传输对象(DTO)、值对象(VO)、普通的 Java 对象(POJO)和 JavaBeans。我们将了解它们之间的区别,并理解应该使用哪种类型以及何时使用。

2、POJO

POJO,也称为 Java 原生类对象,是一种普通的 Java 对象,不引用任何特定的框架。它是一个用于指代简单、轻量级 Java 对象的术语。

POJO 不使用任何属性和方法的命名约定。

让我们定义一个基本的 EmployeePOJO 对象,它具有三个属性:

代码语言:javascript复制
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 对象定义了表示员工的结构,不依赖于任何框架。

3、JavaBeans

3.1. 什么是 JavaBeans?

JavaBeans 与 POJO 类似,但有一些严格的规则需要遵循。

规则规定它应该是可序列化的,具有空构造函数,并允许使用遵循 getX() 和 setX() 约定的方法访问变量。

3.2. 将 POJO 作为 JavaBeans

由于 JavaBeans 本质上是 POJO,让我们通过实现必要的 bean 规则将 EmployeePOJO 转换为 JavaBeans:

代码语言:javascript复制
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 方法访问属性。

4、DTO

4.1. DTO 模式

DTO,也称为数据传输对象,封装了值,以在进程或网络之间传递数据。

这有助于减少调用的方法数量。通过在单个调用中包含多个参数或值,我们减少了远程操作中的网络开销。

该模式的另一个优点是序列化逻辑的封装。它允许程序以特定格式存储和传输数据。

DTO 没有任何显式行为。它基本上通过将域模型与表示层解耦,有助于使代码松耦合。

4.2. 如何使用 DTO?

DTO 具有没有任何业务逻辑的扁平结构。它们使用与 POJO 相同的格式。DTO 只包含与序列化或解析相关的存储、访问器和方法。

DTO 基本上映射到域模型,因此将数据发送到方法或服务器。

让我们创建 EmployeeDTO,它将所有创建员工所需的详细信息分组。我们将在单个请求中向服务器发送这些数据,以优化与 API 的交互:

代码语言:javascript复制
public class EmployeeDTO {

    private String firstName;
    private String lastName;
    private LocalDate startDate;

    // standard getters and setters
}

上述 DTO 与不同的服务进行交互并处理数据流。这个 DTO 模式可以在任何服务中使用,没有任何框架的限制。

5、VO

VO,也称为值对象,是一种特殊类型的对象,可以保存值,例如 java.lang.Integer 和 java.lang.Long。

VO 应该始终覆盖 equals() 和 hashCode() 方法。VO 通常封装小型对象,例如数字、日期、字符串等等。它们遵循值语义,即它们直接更改对象的值并传递副本而不是引用。

将值对象设置为不可变是一个好习惯。值的更改只能通过创建一个新对象而不是更新旧对象本身来发生。这有助于理解两个创建相等的值对象的隐式契约应该保持相等。

让我们定义 EmployeeVO 并覆盖 equals() 和 hashCode() 方法:

代码语言:javascript复制
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);
    }
}

6、结论

在本文中,我们看到了 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 可以用于在应用程序的不同层之间传递值,但一般不包含与业务逻辑相关的方法。

总之,这些模式都是用于封装和传输数据的对象,但它们的具体用途和特点略有不同。选择哪种模式取决于具体的应用场景和需求。


0 人点赞