使用 MongoDB 访问数据

本指南将引导您完成使用 Spring Data MongoDB 构建应用程序的过程,该应用程序将数据存储到基于文档的数据库 MongoDB 中并从中检索数据。

您将构建什么

您将使用 Spring Data MongoDB 将 `Customer` POJO(普通旧 Java 对象)存储在 MongoDB 数据库中。

您需要什么

如何完成本指南

与大多数 Spring 入门指南 一样,您可以从头开始并完成每个步骤,也可以跳过您已经熟悉的步骤。无论哪种方式,您最终都会获得可运行的代码。

要**从头开始**,请继续转到 从 Spring Initializr 开始

要**跳过基础步骤**,请执行以下操作

**完成后**,您可以将您的结果与 `gs-accessing-data-mongodb/complete` 中的代码进行比较。

从 Spring Initializr 开始

您可以使用此 预初始化项目 并单击“生成”以下载 ZIP 文件。此项目已配置为适合本教程中的示例。

要手动初始化项目

  1. 导航到 https://start.spring.io。此服务会引入应用程序所需的所有依赖项,并为您完成大部分设置工作。

  2. 选择 Gradle 或 Maven 以及您要使用的语言。本指南假设您选择了 Java。

  3. 单击**依赖项**并选择**Spring Data MongoDB**。

  4. 单击**生成**。

  5. 下载生成的 ZIP 文件,这是一个使用您选择的选项配置的 Web 应用程序的存档。

如果您的 IDE 集成了 Spring Initializr,则可以在 IDE 中完成此过程。
您也可以从 Github 分支项目并在您的 IDE 或其他编辑器中打开它。

安装并启动 MongoDB

设置好项目后,您可以安装并启动 MongoDB 数据库。

如果您使用的是带有 Homebrew 的 Mac,则可以运行以下命令

$ brew install mongodb

对于 MacPorts,您可以运行以下命令

$ port install mongodb

对于其他具有包管理的系统,例如 Redhat、Ubuntu、Debian、CentOS 和 Windows,请参阅 https://docs.mongodb.org/manual/installation/ 中的说明。

安装 MongoDB 后,您可以通过运行以下命令(这也会启动服务器进程)在控制台窗口中启动它

$ mongod

您应该看到类似于以下的输出

all output going to: /usr/local/var/log/mongodb/mongo.log

定义一个简单的实体

MongoDB 是一个 NoSQL 文档存储。在此示例中,您存储 `Customer` 对象。以下清单显示了 Customer 类(位于 `src/main/java/com/example/accessingdatamongodb/Customer.java` 中)

package com.example.accessingdatamongodb;

import org.springframework.data.annotation.Id;


public class Customer {

  @Id
  public String id;

  public String firstName;
  public String lastName;

  public Customer() {}

  public Customer(String firstName, String lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
  }

  @Override
  public String toString() {
    return String.format(
        "Customer[id=%s, firstName='%s', lastName='%s']",
        id, firstName, lastName);
  }

}

这里有一个 `Customer` 类,它具有三个属性:`id`、`firstName` 和 `lastName`。`id` 主要用于 MongoDB 的内部使用。您还有一个单一构造函数,用于在创建新实例时填充实体。

在本指南中,为了简洁起见,省略了典型的 getter 和 setter 方法。

`id` 符合 MongoDB ID 的标准名称,因此它不需要任何特殊的注解来将其标记为 Spring Data MongoDB。

另外两个属性 `firstName` 和 `lastName` 未添加注解。假设它们映射到与属性本身名称相同的字段。

方便的 `toString()` 方法打印出有关客户的详细信息。

MongoDB 将数据存储在集合中。Spring Data MongoDB 将 `Customer` 类映射到名为 `customer` 的集合。如果您想更改集合的名称,可以在类上使用 Spring Data MongoDB 的 `@Document` 注解。

创建简单的查询

Spring Data MongoDB 专注于将数据存储在 MongoDB 中。它还继承了 Spring Data Commons 项目的功能,例如派生查询的能力。从本质上讲,您无需学习 MongoDB 的查询语言。您可以编写少量方法,查询将自动为您编写。

要查看其工作原理,请创建一个查询 `Customer` 文档的存储库接口,如下面的清单(位于 `src/main/java/com/example/accessingdatamongodb/CustomerRepository.java` 中)所示

package com.example.accessingdatamongodb;

import java.util.List;

import org.springframework.data.mongodb.repository.MongoRepository;

public interface CustomerRepository extends MongoRepository<Customer, String> {

  public Customer findByFirstName(String firstName);
  public List<Customer> findByLastName(String lastName);

}

`CustomerRepository` 扩展了 `MongoRepository` 接口,并插入了它使用的值和 ID 的类型:分别为 `Customer` 和 `String`。此接口包含许多操作,包括标准的 CRUD 操作(创建、读取、更新和删除)。

您可以通过声明其方法签名来定义其他查询。在这种情况下,添加 `findByFirstName`,它实际上是在查找 `Customer` 类型的文档,并查找与 `firstName` 匹配的文档。

您还有 `findByLastName`,它按姓氏查找人员列表。

在典型的 Java 应用程序中,您编写一个实现 `CustomerRepository` 的类并自己编写查询。使 Spring Data MongoDB 如此有用的原因是您无需创建此实现。Spring Data MongoDB 在您运行应用程序时动态创建它。

现在您可以连接此应用程序并查看其外观!

创建应用程序类

Spring Initializr 为应用程序创建了一个简单的类。以下清单显示了 Initializr 为此示例创建的类(位于 `src/main/java/com/example/accessingdatamongodb/AccessingDataMongodbApplication.java` 中)

package com.example.accessingdatamongodb;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class AccessingDataMongodbApplication {

  public static void main(String[] args) {
    SpringApplication.run(AccessingDataMongodbApplication.class, args);
  }

}

`@SpringBootApplication` 是一个便利注解,它添加了以下所有内容

  • `@Configuration`:将类标记为应用程序上下文的 bean 定义的来源。

  • `@EnableAutoConfiguration`:告诉 Spring Boot 根据类路径设置、其他 bean 和各种属性设置开始添加 bean。例如,如果 `spring-webmvc` 位于类路径中,则此注解会将应用程序标记为 Web 应用程序并激活关键行为,例如设置 `DispatcherServlet`。

  • `@ComponentScan`:告诉 Spring 在 `com/example` 包中查找其他组件、配置和服务,使其能够找到控制器。

`main()` 方法使用 Spring Boot 的 `SpringApplication.run()` 方法启动应用程序。您是否注意到没有一行 XML 代码?也没有 `web.xml` 文件。此 Web 应用程序是 100% 纯 Java,您无需处理配置任何管道或基础设施。

只要 Spring Boot 将存储库包含在您的 `@SpringBootApplication` 类的同一个包(或子包)中,它就会自动处理这些存储库。要更精细地控制注册过程,您可以使用 `@EnableMongoRepositories` 注解。

默认情况下,`@EnableMongoRepositories` 会扫描当前包中任何扩展 Spring Data 存储库接口的接口。如果您的项目布局有多个项目并且找不到您的存储库,您可以使用其 `basePackageClasses=MyRepository.class` 通过类型安全地告诉 Spring Data MongoDB 扫描不同的根包。

Spring Data MongoDB 使用 `MongoTemplate` 来执行 `find*` 方法背后的查询。您可以自己使用此模板进行更复杂的查询,但这本指南不涵盖此内容。(请参阅 Spring Data MongoDB 参考指南

现在您需要修改 Initializr 为您创建的简单类。您需要设置一些数据并使用它来生成输出。以下清单显示了完成的 `AccessingDataMongodbApplication` 类(位于 `src/main/java/com/example/accessingdatamongodb/AccessingDataMongodbApplication.java` 中)

package com.example.accessingdatamongodb;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class AccessingDataMongodbApplication implements CommandLineRunner {

  @Autowired
  private CustomerRepository repository;

  public static void main(String[] args) {
    SpringApplication.run(AccessingDataMongodbApplication.class, args);
  }

  @Override
  public void run(String... args) throws Exception {

    repository.deleteAll();

    // save a couple of customers
    repository.save(new Customer("Alice", "Smith"));
    repository.save(new Customer("Bob", "Smith"));

    // fetch all customers
    System.out.println("Customers found with findAll():");
    System.out.println("-------------------------------");
    for (Customer customer : repository.findAll()) {
      System.out.println(customer);
    }
    System.out.println();

    // fetch an individual customer
    System.out.println("Customer found with findByFirstName('Alice'):");
    System.out.println("--------------------------------");
    System.out.println(repository.findByFirstName("Alice"));

    System.out.println("Customers found with findByLastName('Smith'):");
    System.out.println("--------------------------------");
    for (Customer customer : repository.findByLastName("Smith")) {
      System.out.println(customer);
    }

  }

}

`AccessingDataMongodbApplication` 包含一个 `main()` 方法,该方法会自动装配 `CustomerRepository` 的实例。Spring Data MongoDB 会动态创建一个代理并将其注入到此处。我们通过一些测试来使用 `CustomerRepository`。首先,它保存少量 `Customer` 对象,演示 `save()` 方法并设置一些要使用的数据。接下来,它调用 `findAll()` 从数据库中获取所有 `Customer` 对象。然后,它调用 `findByFirstName()` 按名字获取单个 `Customer`。最后,它调用 `findByLastName()` 查找所有姓氏为 `Smith` 的客户。

默认情况下,Spring Boot 尝试连接到本地托管的 MongoDB 实例。阅读 参考文档,了解有关将应用程序指向其他地方托管的 MongoDB 实例的详细信息。

构建可执行 JAR

您可以使用 Gradle 或 Maven 从命令行运行应用程序。您还可以构建一个包含所有必要依赖项、类和资源的单个可执行 JAR 文件,然后运行该文件。构建可执行 JAR 文件可以轻松地在整个开发生命周期中、在不同环境中交付、版本化和部署服务作为应用程序。

如果您使用 Gradle,可以使用 `./gradlew bootRun` 运行应用程序。或者,您可以使用 `./gradlew build` 构建 JAR 文件,然后运行 JAR 文件,如下所示

java -jar build/libs/gs-accessing-data-mongodb-0.1.0.jar

如果您使用 Maven,可以使用 `./mvnw spring-boot:run` 运行应用程序。或者,您可以使用 `./mvnw clean package` 构建 JAR 文件,然后运行 JAR 文件,如下所示

java -jar target/gs-accessing-data-mongodb-0.1.0.jar
此处描述的步骤创建了一个可运行的 JAR。您还可以 构建经典的 WAR 文件

由于 `AccessingDataMongodbApplication` 实现了 `CommandLineRunner`,因此在 Spring Boot 启动时会自动调用 `run` 方法。您应该看到类似于以下内容(以及其他输出,例如查询)

== Customers found with findAll():
Customer[id=51df1b0a3004cb49c50210f8, firstName='Alice', lastName='Smith']
Customer[id=51df1b0a3004cb49c50210f9, firstName='Bob', lastName='Smith']

== Customer found with findByFirstName('Alice'):
Customer[id=51df1b0a3004cb49c50210f8, firstName='Alice', lastName='Smith']
== Customers found with findByLastName('Smith'):
Customer[id=51df1b0a3004cb49c50210f8, firstName='Alice', lastName='Smith']
Customer[id=51df1b0a3004cb49c50210f9, firstName='Bob', lastName='Smith']

总结

恭喜!您设置了一个 MongoDB 服务器,并编写了一个简单的应用程序,该应用程序使用 Spring Data MongoDB 将对象保存到数据库并从中获取对象,而无需编写具体的存储库实现。

如果您想轻松地使用基于超媒体的 RESTful 前端公开 MongoDB 存储库,请阅读 使用 REST 访问 MongoDB 数据

另请参阅

以下指南可能也有帮助

想编写新的指南或为现有指南贡献代码?请查看我们的贡献指南

所有指南的代码均采用ASLv2许可证发布,文字内容则采用署名-非衍生作品创作共用许可证

获取代码