A Guide to @DBRef in MongoDB – MongoDB中的@DBRef指南

最后修改: 2022年 3月 18日

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

1. Overview

1.概述

In this tutorial, we’ll look at Spring Data MongoDB’s @DBRef annotation. We’ll connect MongoDB documents using this annotation. Additionally, we’ll see the types of MongoDB database references and compare them as well.

在本教程中,我们将了解 Spring Data MongoDB 的 @DBRef 注解。我们将使用该注解连接MongoDB文档。此外,我们还将看到MongoDB数据库引用的类型,并对它们进行比较。

2. MongoDB Manual Database Reference

2.MongoDB手册数据库参考

The first type that we discuss is called the manual reference. In MongoDB, every document must have an id field. Therefore, we can rely on using it and connect documents with it.

我们讨论的第一种类型被称为手动引用。在MongoDB中,每个文档都必须有一个id。因此,我们可以依靠使用它,用它来连接文档。

When using manual references, we store the _id of the referenced document in another document. 

当使用手动引用时,我们将被引用文件的_id存储在另一个文件中。

Later on, when we are querying data from the first collection, we can start a second query to fetch the referenced documents.

后来,当我们从第一个集合中查询数据时,我们可以启动第二个查询来获取被引用的文件。

3. Spring Data MongoDB @DBRef Annotation

3.Spring Data MongoDB @DBRef 注释

DBRefs are similar to manual references in the sense that they also contain the referenced document’s _id. However, they contain the referenced document’s collection in the $ref field and optionally its database as well in the $db field.

DBRefs与手动引用类似,因为它们也包含被引用文档的_id但是,它们在$ref字段中包含了被引用文档的集合,并且在$db字段中也可以选择包含其数据库。

The advantage of this over manual references is that it clarifies which collection we are referencing.

与手动引用相比,这样做的好处是可以明确我们引用的是哪个集合。

4. Application Setup

4.应用程序的设置

4.1. Dependency

4.1.依赖性

Firstly, we need to add the required dependencies to use MongoDB with Spring Boot.

首先,我们需要添加所需的依赖项,以便在Spring Boot中使用MongoDB。

Let’s add spring-boot-starter-data-mongodb to our pom.xml:

让我们把spring-boot-starter-data-mongodb加入我们的pom.xml

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>

4.2. Configuration

4.2.配置

Now, we set up the connection by adding the following configuration to the application.properties file:

现在,我们通过向application.properties文件添加以下配置来设置连接:

spring.data.mongodb.host=localhost
spring.data.mongodb.port=27017
spring.data.mongodb.database=person_database

Let’s run the application to test whether we can connect to the database. We should see a message similar to this in the logs:

让我们运行应用程序来测试我们是否能连接到数据库。我们应该在日志中看到类似这样的消息:

Opened connection [connectionId{localValue:2, serverValue:37}] to localhost:27017

This means that the application could successfully connect to MongoDB.

这意味着应用程序可以成功地连接到MongoDB.

4.3. Collections

4.3.收藏

In MongoDB, we use collections to store individual documents. They are the counterpart of tables in relational databases.

在MongoDB中,我们使用 collections来存储单个文档。它们与关系型数据库中的表相对应。

In this example, we’ll work with three different data types: Person, Dog, and Cat. We’ll connect persons to their pets.

在这个例子中,我们将处理三种不同的数据类型。。我们将把人和他们的宠物联系起来。

Let’s create the collections in the database with some data. We can use Mongo Express for this, but any other tool would work as well.

让我们用一些数据在数据库中创建集合。我们可以使用Mongo Express来做这件事,但任何其他工具也可以工作。

Firstly, let’s create a database named person_database and create two collections inside it named Dog and Cat. We’ll insert one document into each one. To simplify, both of them will have only one property: the pet’s name.

首先,让我们创建一个名为person_database的数据库,并在其中创建两个名为DogCat.的集合,我们将在每个集合中插入一个文档。为了简化,它们都将只有一个属性:宠物的名字。

Let’s insert this document into the Dog collection:

让我们把这个文件插入到Dog集合。

{
    _id: ObjectID("622112d71f9dac417b84227d"), 
    name: "Max"
}

Then, let’s insert this document into the Cat collection:

然后,让我们把这个文件插入到Cat集合:

{
    _id: ObjectID("622112781f9dac417b84227b"),
    name: "Loki"
}

Now, let’s create the Person collection and insert a document into it:

现在,让我们创建Person集合并向其中插入一个文档:

{
    _id: ObjectId(),
    name: "Bob",
    pets: [
        {
          "$ref": "Cat",
          "$id": "622112781f9dac417b84227b",
          "$db": ""
        },    
        {
          "$ref": "Dog",
          "$id": "622112d71f9dac417b84227d",
          "$db": ""
        }
    ]
}

We provide the pets as an array. The items of the array need to follow a specific format to be able to use them as DBRefs. We need to provide the name of the collection in the $ref property. In this case, it’s Cat and Dog. Then, we include the ID of the referenced documents. Lastly, we can optionally include a database name in the $db property if we would like to reference the collections from a different database.

我们以一个数组的形式提供宠物。数组中的项目需要遵循特定的格式,以便能够将它们用作DBRefs。我们需要在$ref属性中提供集合的名称。在本例中,它是CatDog。然后,我们包括被引用文档的ID。最后,如果我们想从一个不同的数据库中引用集合,我们可以选择在$db属性中包括一个数据库名称。

5. Using the @DBRef Annotation

5.使用@DBRef注释

We can map the previously created collections to Java classes, similar to what we would do when working with a relational database.

我们可以将之前创建的集合映射到Java类,类似于我们在使用关系型数据库时的做法。

To simplify, we won’t create separate classes for the Dog and Cat data types. Instead, we’ll use a Pet class that contains an ID and a name:

为了简化,我们将不为DogCat数据类型创建单独的类。相反,我们将使用一个Pet类,其中包含一个ID和一个名字。

public class Pet {
    private String id;
    private String name;

    @Override 
    public String toString() {
        return "Pet [id=" + id + ", name=" + name + "]";
    }

    // standard getters and setters
}

Now, we’ll create the Person class and include an association to the Pet class via @DBRef:

现在,我们将创建类,并包括与宠物类的关联,通过@DBRef:

@Document(collection = "Person")
public class Person {

    @Id
    private String id;
    
    private String name;

    @DBRef
    private List<Pet> pets;

    @Override 
    public String toString() {
        return "Person [id=" + id + ", name=" + name + ", pets=" + pets + "]";
    }

    // standard getters and setters
}

Next, let’s create a simple repository to be able to query data:

接下来,让我们创建一个简单的repository,以便能够查询数据:

public interface PersonRepository extends MongoRepository<Person, String> {}

We’ll test everything by creating an ApplicationRunner that executes a MongoDB query when we start the application. Let’s override the run() method and put a log statement so we can see the contents of the Person collection:

我们将通过创建一个ApplicationRunner来测试一切,当我们启动应用程序时,它会执行一个 MongoDB 查询。让我们重写run()方法,并放入一个日志语句,以便我们可以看到Person集合的内容。

@Override
public void run(ApplicationArguments args) throws Exception {
    logger.info("{}", personRepository.findAll());
}

This produces a log output similar to this because we have overridden the toString() method in our entity classes:

这产生了一个类似于这样的日志输出,因为我们在实体类中重写了toString()方法。

com.baeldung.mongodb.dbref.DbRefTester : [Person [id=62249c5c7ffe83c50ad12700, name=Bob, pets=[Pet [id=622112781f9dac417b84227b, name=Loki], Pet [id=622112d71f9dac417b84227d, name=Max]]]]

This means that we successfully read and joined documents from different collections.

这意味着我们成功地读取并加入了来自不同集合的文档

5.1. Reference a Different Database

5.1.引用一个不同的数据库

The @DBRef annotation accepts two parameters. One of them is the db parameter, which can be used to reference documents in other databases.

@DBRef注释接受两个参数。其中一个是db参数,它可以用来引用其他数据库中的文档。

This is optional, which means that the application looks for referenced documents in the same database if we don’t provide this value.

这是可选的,这意味着如果我们不提供这个值,应用程序会在同一个数据库中寻找被引用的文档。

In our case, if the Cat or Dog would reside in a different database named pet_database, we would need to change the annotation to this: @DBRef(db = “pet_database”).

在我们的案例中,如果将驻留在一个名为pet_database>的不同数据库中,我们将需要把注释改为这样。@DBRef(db = “pet_database”)

5.2. Lazy Loading

5.2.懒惰的加载

The other parameter accepted by the annotation is called lazy. This is a boolean value that determines if the referenced documents should be loaded lazily or not.

注解接受的另一个参数叫做lazy。这是一个boolean值,它决定了被引用的文档是否应该被懒惰地加载。

By default, it is false, which means that the references will be loaded eagerly when we query the main entity. If we turn this feature on, the referenced documents will not be loaded until they are accessed first.

默认情况下,它是false,这意味着当我们查询主实体时,引用将被急切地加载。如果我们打开这个功能,引用的文件将不会被加载,直到它们被首先访问。

6. Conclusion

6.结论

In this article, we compared MongoDB manual references with Spring Data MongoDB @DBRef. We created three collections and connected them with this annotation. We created a Spring Boot application to query these collections using a MongoRepository and displayed the related documents.

在这篇文章中,我们将MongoDB的手动引用与Spring Data MongoDB的@DBRef进行了比较。我们创建了三个集合,并用这个注解将它们连接起来。我们创建了一个Spring Boot应用程序,使用MongoRepository查询这些集合,并显示相关文档。

As always, the source code for the examples is available over on GitHub.

像往常一样,这些例子的源代码可以在GitHub上找到