1. 概述
在本教程中,我们将研究Spring Data MongoDB的 @DBRef 注解。我们将使用这个注释连接MongoDB文档。此外,我们还将了解MongoDB数据库引用的类型并对它们进行比较。
2. MongoDB手册数据库参考
我们讨论的第一种类型称为手工引用。在MongoDB中,每个文档都必须有一个_id
字段。因此,我们可以依赖于使用它,并使用它连接文档。
当使用手动引用时,我们将被引用文档的 _id 存储在另一个文档中。
稍后,当我们从第一个集合中查询数据时,我们可以启动第二个查询来获取引用的文档。
3. Spring Data MongoDB的 @DBRef
注解
DBRef
类似于手动引用,因为它们也包含被引用文档的 _id
。 但是,它们在 $ref
字段中包含被引用文档的集合,在 $db
字段中也包含可选的数据库。
与手动引用相比,它的优势在于它明确了我们引用的是哪个集合。
4. 应用程序设置
4.1. 依赖
首先,我们需要添加使用 MongoDB 和 Spring Boot 所需的依赖项。
让我们将 spring-boot-starter-data-mongodb 添加到我们的 pom.xml 中:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
4.2. 配置
现在,我们通过将以下配置添加到 application.properties 文件来设置连接:
spring.data.mongodb.host=localhost
spring.data.mongodb.port=27017
spring.data.mongodb.database=person_database
让我们运行应用程序来测试我们是否可以连接到数据库。 我们应该在日志中看到与此类似的消息:
Opened connection [connectionId{localValue:2, serverValue:37}] to localhost:27017
这意味着应用程序可以成功连接到 MongoDB。
4.3. Collections
在 MongoDB 中,我们使用 collections 来存储单个文档。 它们是关系数据库中的表的对应物。
在此示例中,我们将使用三种不同的数据类型:Person、Dog 和 Cat。 我们会将人与他们的宠物联系起来。
让我们用一些数据在数据库中创建集合。 为此,我们可以使用 Mongo Express,但任何其他工具也可以。
首先,让我们创建一个名为 person_database 的数据库,并在其中创建两个名为 Dog 和 Cat 的集合。我们将在每个集合中插入一个文档。 为简化起见,它们都只有一个属性:宠物的名字。
让我们将此文档插入到 Dog 集合中:
{
_id: ObjectID("622112d71f9dac417b84227d"),
name: "Max"
}
然后,让我们将此文档插入到 Cat 集合中:
{
_id: ObjectID("622112781f9dac417b84227b"),
name: "Loki"
}
现在,让我们创建 Person 集合并在其中插入一个文档:
{
_id: ObjectId(),
name: "Bob",
pets: [
{
"$ref": "Cat",
"$id": "622112781f9dac417b84227b",
"$db": ""
},
{
"$ref": "Dog",
"$id": "622112d71f9dac417b84227d",
"$db": ""
}
]
}
我们以数组的形式提供宠物。 数组的项目需要遵循 特定格式 才能将它们用作 DBRef。我们需要在 $ref
属性中提供集合的名称。 在这种情况下,它是 Cat 和 Dog。然后,我们包含引用文档的 ID。最后,如果我们想引用来自不同数据库的集合,我们可以选择在 $db
属性中包含数据库名称。
5. 使用@DBRef
注解
我们可以将之前创建的集合映射到 Java 类,类似于我们在使用关系数据库时所做的事情。
为简化起见,我们不会为 Dog 和 Cat 数据类型创建单独的类。 相反,我们将使用包含 ID 和名称的 Pet 类:
public class Pet {
private String id;
private String name;
@Override
public String toString() {
return "Pet [id=" + id + ", name=" + name + "]";
}
// standard getters and setters
}
现在,我们将创建 Person 类并通过 @DBRef: 包含与 Pet 类的关联
@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
}
接下来,让我们创建一个简单的 repository 来查询数据:
public interface PersonRepository extends MongoRepository<Person, String> {}
我们将通过创建一个在启动应用程序时执行 MongoDB 查询的 [ApplicationRunner] 来测试所有内容。 让我们重写 run() 方法并添加一条日志语句,这样我们就可以看到 Person 集合的内容:
@Override
public void run(ApplicationArguments args) throws Exception {
logger.info("{}", personRepository.findAll());
}
这会产生与此类似的日志输出,因为我们已经覆盖了实体类中的 toString() 方法:
com.baeldung.mongodb.dbref.DbRefTester : [Person [id=62249c5c7ffe83c50ad12700, name=Bob, pets=[Pet [id=622112781f9dac417b84227b, name=Loki], Pet [id=622112d71f9dac417b84227d, name=Max]]]]
这意味着我们成功地读取并加入了来自不同集合的文档。
5.1. 引用不同的数据库
@DBRef 注释接受两个参数。 其中之一是 db 参数,可用于引用其他数据库中的文档。
这是可选的,这意味着如果我们不提供此值,应用程序将在同一数据库中查找引用的文档。
在我们的例子中,如果 Cat 或 Dog 将驻留在名为 pet_database 的不同数据库中,我们需要将注释更改为:@DBRef(db = “pet_database”)。
5.2. 延迟加载
注释接受的另一个参数称为 lazy。 这是一个 boolean 值,用于确定是否应该延迟加载引用的文档。
默认是false,这意味着当我们查询主实体时,引用将被急切地加载。 如果我们打开这个功能,引用的文档将不会被加载,直到它们被首先访问。
6. 结尾
在本文中,我们将 MongoDB 手动引用与 Spring Data MongoDB @DBRef. 进行了比较。我们创建了三个集合并将它们与此注解连接起来。 我们创建了一个 Spring Boot 应用程序来使用 MongoRepository 查询这些集合并显示相关文档。