What Does It Mean to Hydrate an Object? – 物体水化意味着什么?

最后修改: 2023年 12月 20日

中文/混合/英文(键盘快捷键:t)

1. Introduction

1.导言

In this tutorial, we’ll talk about the term hydration in the context of programming and dive deep into what it means to hydrate a Java object. 

在本教程中,我们将讨论编程中的水合一词,并深入探讨 Java 对象水合的含义。

2. Object Hydration

2.物体水合

2.1. Lazy Initialization

2.1.懒惰初始化

Lazy loading or lazy initialization of an object is a common pattern used in software applications. An object in Java is an instance of a class created using the new keyword. Objects are the building blocks of a program, and objects interact with other objects to achieve a desired functionality. 

Lazy loading 或对象的懒初始化是软件应用程序中常用的一种模式。Java 中的对象是使用 new 关键字创建的类实例。对象是程序的构件,对象与其他对象交互以实现所需的功能。

Objects are generally meant to represent a real-world entity in object-oriented programming paradigm, and hence, objects have several associated properties. Object initialization refers to the process of populating the properties of the object with real data. This is generally done by invoking a class constructor and passing in data as arguments. Initialization can also be done from a data source such as a network, database, or file system. 

在面向对象编程范式中,对象通常用于表示现实世界中的实体,因此对象具有若干相关属性。Object 初始化是指使用真实数据填充对象属性的过程。初始化也可以通过网络、数据库或文件系统等数据源完成。

Object initializations can, at times, be a resource-intensive operation, especially when the data is being fed from a different data source. Also, objects are not always used by the program immediately upon creation. 

对象初始化有时是一项资源密集型操作,尤其是当数据来自不同的数据源时。此外,对象并不总是在创建后立即被程序使用。

In such scenarios, it is a good practice to defer the object initialization as long as possible until the point it is needed. This pattern is called lazy initialization, as we create the object with empty data at one time and lazily populate the object with relevant data in the future. A conscious delay of the data initialization helps boost code performance and memory utilization.

在这种情况下,将对象初始化尽可能推迟到需要的时候,不失为一种好的做法。这种模式被称为 “懒初始化”,因为我们在创建对象时一次性使用空数据,并在将来懒散地将相关数据填充到对象中。有意识地延迟数据初始化有助于提高代码性能和内存利用率

Let’s create a User class which has several attributes:

让我们创建一个具有多个属性的 User 类:

public class User {
    private String uId;
    private String firstName;
    private String lastName;
    private String alias;
    // constructor, getter-setters
}

We can create an object of User and keep it in memory without filling its attributes with meaningful data:

我们可以创建一个 User 对象,并将其保存在内存中,而无需在其属性中填充有意义的数据:

User iamUser = new User();

2.2. What Is Hydration?

2.2.什么是水合?

With lazy initialization, we deliberately delay the initialization process of an object that is already created and exists in memory. The process of populating data to an existing empty object is called hydration.

对于已经创建并存在于内存中的对象,使用懒初始化时,我们会故意延迟其初始化过程。向现有空对象填充数据的过程称为水合。

The User instance we created is a dummy instance. The object does not have any relevant data attributes, as it wasn’t required until this point. To make the object useful, we should fill the object with relevant domain data, which can be done by filling it with data from a source such as a network, database, or file system. 

我们创建的用户实例是一个虚拟实例。该对象没有任何相关数据属性,因为在此之前并不需要。为了使该对象有用,我们应该用相关的域数据填充该对象,这可以通过从网络、数据库或文件系统等来源填充数据来实现。

We perform the hydration of the user instance in the following steps. We first write our hydration logic as a class-level method, which uses the class setters to set the relevant data. In our example, we’ll use our data. However, we can fetch data from a file or a similar source as well:

我们按以下步骤对用户实例进行水合。首先,我们将水合逻辑写成一个类级方法,使用类设置器来设置相关数据。在我们的示例中,我们将使用自己的数据。不过,我们也可以从文件或类似来源获取数据:

public void generateMyUser() {
    this.setAlias("007");
    this.setFirstName("James");
    this.setLastName("Bond");
    this.setuId("JB");
}

Now we create an empty instance of User, and when required, we hydrate the same instance by calling the generateMyUser() method:

现在,我们创建了一个 User 的空实例,并在需要时,通过调用 generateMyUser() 方法将同一实例水合:

User jamesBond = new User();
// performing hydration
jamesBond.generateMyUser();

We can validate the results of the hydration by asserting the state of its attributes:

我们可以通过断言水合的属性状态来验证水合的结果:

User jamesBond = new User();
Assert.assertNull(jamesBond.getAlias());

jamesBond.generateMyUser();
Assert.assertEquals("007", jamesBond.getAlias());

3. Hydration and Deserialization

3.水化和脱ial

Hydration and Deserialization are not synonymous, and we should not use them interchangeably. Deserialization is a process used in programming to revive or recreate an object from its serialized form. We often store or transmit objects over a network. During the process, serialization (the conversion of the object to a stream of bytes) and deserialization (the reverse process of reviving the object) come in very handy. 

水合与反序列化并非同义词,我们不应交替使用。反序列化是编程中用于从序列化形式恢复或重新创建对象的过程。在此过程中,序列化(将对象转换为字节流)和反序列化(恢复对象的逆过程)非常有用。

We can serialize our User instance into a file or equivalent:

我们可以将 User 实例序列化为文件或类似文件:

try {
    FileOutputStream fileOut = new FileOutputStream(outputName);
    ObjectOutputStream out = new ObjectOutputStream(fileOut);
    out.writeObject(user);
    out.close();
    fileOut.close();
} catch (IOException e) {
    e.printStackTrace();
}

Similarly, when required, we can recreate the User instance from its serialized form:

同样,在需要时,我们可以根据序列化形式重新创建 User 实例:

try {
    FileInputStream fileIn = new FileInputStream(serialisedFile);
    ObjectInputStream in = new ObjectInputStream(fileIn);
    deserializedUser = (User) in.readObject();
    in.close();
    fileIn.close();
} catch (IOException | ClassNotFoundException e) {
    e.printStackTrace();
}

It is clear that hydration and deserialization both involve dealing with an object and filling it with data. However, the important difference between the two is that deserialization is mostly a single-step process of creating the instance and populating the attributes.

很明显,水合和反序列化都涉及处理对象并向其填充数据。然而,两者之间的重要区别在于,反序列化主要是一个创建实例和填充属性的单步过程。

Hydration, on the other hand, is concerned with only adding the data to the attributes of a pre-formed object. Therefore, deserialization is object instantiation and object hydration in the same step. 

另一方面,水合只涉及将数据添加到预成型对象的属性中。因此,反序列化就是在同一步骤中进行对象实例化和对象水合。

4. Hydration in ORM Frameworks

4.ORM 框架中的水合作用

An ORM (Object Relational Mapping) framework is a software development paradigm that enables us to combine object-oriented programming with relational databases. ORM frameworks facilitate the mapping between the objects in the application code and the tables in a relational database and allow developers to interact with database entities as native objects. 

ORM(对象关系映射)框架是一种软件开发范式,它使我们能够将面向对象编程与关系数据库结合起来。对象关系映射框架促进了应用程序代码中的对象与关系数据库中的表之间的映射,并允许开发人员将数据库实体作为本地对象进行交互。

The idea of object hydration is more prevalent in ORM frameworks, such as Hibernate or JPA.

对象水合的想法在 ORM 框架中更为普遍,例如 Hibernate 或 JPA

Let’s consider a JPA Entity class Book and its corresponding Repository class as follows:

让我们考虑一个 JPA Entity 类 Book 及其相应的 Repository 类,如下所示:

@Entity
@Table(name = "books")
public class Book {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column(name = "name")
    private String name;
    // other columns and methods
}
public interface BookRepository extends JpaRepository<Book, Long> {
}

Based on ORM principles, the entity Book represents a table in our relational database. The entities’ interactions with the database are abstracted in the form of the BookRepository interface that we have defined above. An instance of the class represents a row in the table. 

根据 ORM 原则,实体 Book 代表关系数据库中的一个表。实体与数据库的交互以我们在上面定义的 BookRepository 接口的形式进行了抽象。该类的一个实例代表表中的一行。

When we load an instance of Book from the database by using one of the numerous inbuilt find() methods or using custom queries, the ORM framework performs several steps:

当我们使用大量内置 find() 方法或自定义查询从数据库加载 Book 实例时,ORM 框架会执行几个步骤:

Book aTaleOfTwoCities = bookRepository.findOne(1L);

The framework initializes an empty object, typically by calling the default constructor of the class. Once the object is ready, the framework tries to load the attribute data from a cache store. If there is a cache miss at this point, the framework establishes a connection with the database and queries the table to fetch the row.

框架会初始化一个空对象,通常是通过调用类的默认构造函数。 一旦对象准备就绪,框架就会尝试从缓存中加载属性数据。如果此时出现缓存缺失,框架就会与数据库建立连接,并查询表以获取行。

Once the ResultSet is obtained, the framework hydrates the aforementioned object aTaleOfTwoCities with the resultset object and finally returns the instance. 

一旦获得结果集,框架就会将上述对象 aTaleOfTwoCities 与结果集对象水合,并最终返回实例。

5. Conclusion

5.结论

In this article, we discussed the meaning of the term hydration in the context of programming. We saw how hydration differs from deserialization. Finally, we explored examples of object hydration in ORM frameworks and plain object models. 

在本文中,我们讨论了水合一词在编程中的含义。我们还了解了水合与反序列化的区别。最后,我们探讨了 ORM 框架和普通对象模型中对象水合的示例。

As usual, the code for this article is available over on GitHub.

与往常一样,本文的代码可在 GitHub 上获取。