Quarkus 整合 Mongodb

1、简介

Quarkus 是一个流行的 Java 框架,经过优化,可用于创建内存占用小、启动速度极快的应用。

与流行的 NoSQL 数据库 MongoDB 搭配使用时,Quarkus 为开发高性能、可扩展的应用提供了强大的工具包。

本文将带你了解如何使用 Quarkus 配置 MongoDB、实现基本的 CRUD 操作,以及如何使用 Quarkus 的 Panache(Object Document Mapper,ODM)来简化这些操作。

2、配置

2.1、Maven 依赖

要在 Quarkus 中使用 MongoDB,需要添加 quarkus-mongodb-client 依赖:

<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-mongodb-client</artifactId>
    <version>3.13.0</version>
</dependency>

该依赖提供了使用 MongoDB Java 客户端与 MongoDB 数据库交互的必要工具。

2.2、运行 MongoDB 数据库

本文采用 Docker 的方式运行 MongoDB,这种方式非常便捷,无需在机器上直接安装 MongoDB。

从 Docker Hub 拉取 MongoDB 镜像:

docker pull mongo:latest

启动一个新的容器:

docker run --name mongodb -d -p 27017:27017 mongo:latest

2.3、配置 MongoDB 数据库

要配置的主要属性是访问 MongoDB 的 URL。我们可以在 connection 字符串中包含几乎所有的配置。

可以为多个节点的副本集配置 MongoDB 客户端,但在我们的示例中,使用的是 localhost 上的单机节点:

quarkus.mongodb.connection-string = mongodb://localhost:27017

3、基本的 CRUD 操作

数据库就绪后,现在让我们使用 Quarkus 提供的默认 Mongo 客户端实现基本的 CRUD(创建、读取、更新、删除)操作。

3.1、定义实体

定义 Article 实体,表示 MongoDB collection 中的一个文档:

public class Article {
    @BsonId
    public ObjectId id;
    public String author;
    public String title;
    public String description;
    
    // Getter / Setter 省略
}

如上,Article 类包括 idauthortitledescription 字段。ObjectId 是 BSON(JSON 的二进制表示)类型,用作 MongoDB 文档的默认 ID。

@BsonId 注解将一个字段指定为 MongoDB 文档的 ID(_id)。当注解在一个字段上时,它表示该字段应映射到 MongoDB collection 中的 _id 字段。通过这种组合,我们可以确保每个 Article 文档都有一个唯一的 ID,MongoDB 可以用它来高效地索引和检索文档。

3.2、定义 Repository

创建 ArticleRepository 类,使用 MongoClientArticle 实体执行 CRUD 操作。该类将管理与 MongoDB 数据库的连接,并提供创建、读取、更新和删除 Article 文档的方法。

首先,注入 MongoClient 实例:

@Inject
MongoClient mongoClient;

通过 MongoClient 实例,我们可以与 MongoDB 数据库交互,而无需手动管理连接。

定义一个工具方法 getCollection(),用于从 articles 数据库中获取 articles collection:

private MongoCollection<Article> getCollection() {
    return mongoClient.getDatabase("articles").getCollection("articles", Article.class);
}

现在,可以使用 getCollection() 返回的 MongoCollection 来执行基本的 CRUD 操作:

public void create(Article article) {
    getCollection().insertOne(article);
}

create() 会使用 insertOne() 方法在 MongoDB collection 中插入一个新的 Article 文档:

public List<Article> listAll() {
    return getCollection().find().into(new ArrayList<>());
}

listAll() 方法可从 MongoDB collection 中检索所有 Article 文档。它利用 find() 方法查询并收集所有文档。我们还可以指定要返回的集合类型。

public void update(Article article) {
    getCollection().replaceOne(new org.bson.Document("_id", article.id), article);
}

update() 方法用提供的对象替换现有的 Article 文档。该方法使用 replaceOne() 查找与 _id 匹配的文档,并用新数据对其进行更新。

public void delete(String id) {
    getCollection().deleteOne(new org.bson.Document("_id", new ObjectId(id)));
}

delete() 方法根据 ID 从 collection 中删除 Article 文档。该方法会构建一个与 _id 匹配的 Filter,并使用 deleteOne 删除与该 Filter 匹配的第一个文档。

3.3、定义 Resource

为了简单,本文仅定义 Resource 和 Repository,而不实现 Service。

现在,我们需要做的就是创建 Resource、注入 Repository,并为每个操作创建一个方法:

@Path("/articles")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class ArticleResource {
    @Inject
    ArticleRepository articleRepository;

    @POST
    public Response create(Article article) {
        articleRepository.create(article);
        return Response.status(Response.Status.CREATED).build();
    }

    @GET
    public List<Article> listAll() {
        return articleRepository.listAll();
    }

    @PUT
    public Response update(Article updatedArticle) {
        articleRepository.update(updatedArticle);
        return Response.noContent().build();
    }

    @DELETE
    @Path("/{id}")
    public Response delete(@PathParam("id") String id) {
        articleRepository.delete(id);
        return Response.noContent().build();
    }
}

3.4、测试 API

我们可以使用 curl 命令行工具来测试 API。

首先,在数据库中添加一篇新文章,使用 HTTP POST 方法将表示文章的 JSON payload 发送到 /articles 端点:

curl -X POST http://localhost:8080/articles \
-H "Content-Type: application/json" \
-d '{"author":"John Doe","title":"Introduction to Quarkus","description":"A comprehensive guide to the Quarkus framework."}'

使用 HTTP GET 方法从数据库中获取所有文章,以验证文章是否已成功存储:

curl -X GET http://localhost:8080/articles

这会返回一个 JSON 数组,其中包含当前存储在数据库中的所有文章:

[
  {
    "id": "66a8c65e8bd3a01e0a509f0a",
    "author": "John Doe",
    "title": "Introduction to Quarkus",
    "description": "A comprehensive guide to Quarkus framework."
  }
]

4、使用 Panache

Quarkus 提供了一个名为 Panache 的额外抽象层,可以简化数据库操作,减少模板代码。有了 Panache,我们就可以把更多精力放在业务逻辑上,而不是数据访问代码上。

来看看如何使用 Panache 实现相同的 CRUD 操作。

4.1、Maven 依赖

要在 MongoDB 中使用 Panache,需要添加 quarkus-mongodb-panache 依赖:

<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-mongodb-panache</artifactId>
    <version>3.13.0</version>
</dependency>

4.2、定义实体

使用 Panache 时,实体类需要继承 PanacheMongoEntity,它提供了用于常见数据库操作的内置方法。还要使用 @MongoEntity 注解来定义 MongoDB 集合:

@MongoEntity(collection = "articles", database = "articles")
public class Article extends PanacheMongoEntityBase {
    private ObjectId id;
    private String author;
    private String title;
    private String description;

    // Getter / Setter 方法省略
}

4.3、定义 Repository

通过实现 PanacheMongoRepository 来创建一个 Repository。这为我们提供了 CRUD 操作,而无需编写模板代码:

@ApplicationScoped
public class ArticleRepository implements PanacheMongoRepository<Article> {}

实现 PanacheMongoRepository 类,我们可以直接使用 persistence()listAll()findById 等方法,用于执行 CRUD 操作和管理 MongoDB 实体。

4.4、定义 Resource

现在,创建新的 Resource,使用新的 Repository:

@Path("/v2/articles")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class ArticleResource {
    @Inject
    ArticleRepository articleRepository;

    @POST
    public Response create(Article article) {
        articleRepository.persist(article);
        return Response.status(Response.Status.CREATED).build();
    }

    @GET
    public List<Article> listAll() {
        return articleRepository.listAll();
    }

    @PUT
    public Response update(Article updatedArticle) {
        articleRepository.update(updatedArticle);
        return Response.noContent().build();
    }

    @DELETE
    @Path("/{id}")
    public Response delete(@PathParam("id") String id) {
        articleRepository.delete(id);
        return Response.noContent().build();
    }
}

4.5、测试 API

可以使用与上述示例中相同的 curl 命令来测试新的 API。唯一要改变的是调用的 endpont,这次调用的是 /v2/articles API。

创建新文章:

curl -X POST http://localhost:8080/v2/articles \
-H "Content-Type: application/json" \
-d '{"author":"John Doe","title":"Introduction to MongoDB","description":"A comprehensive guide to MongoDB."}'

检索所有文章:

curl -X GET http://localhost:8080/v2/articles

5、总结

本文介绍了如何在 Quarkus 中整合、使用 MongoDB,以及如何使用默认的 Mongo 客户端和 Panache(ODM)来操作数据库和文档。


Ref:https://www.baeldung.com/java-quarkus-mongodb