MongoDB 和 Quarkus 入门

Quarkus 是一个流行的 Java 框架,针对创建占用内存最少且启动时间较快的应用程序进行了优化。

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

在本教程中,我们将探索使用 Quarkus 配置 MongoDB,实现基本的CRUD操作,以及如何使用 Panache(Quarkus 的对象文档映射器 (ODM))简化这些操作。

Maven 依赖
要将 MongoDB 与 Quarkus 一起使用,我们需要包含quarkus-mongodb-client依赖项:

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

此依赖项提供了使用 MongoDB Java 客户端与 MongoDB 数据库交互所需的工具。

运行 MongoDB 数据库
在本文中,我们将在 Docker 容器中运行 MongoDB。这是一种设置 MongoDB 实例的便捷方法,无需直接在我们的机器上安装 MongoDB。

我们首先从 Docker Hub 中提取 MongoDB 镜像:

docker pull mongo:latest

并启动一个新容器:

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

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

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

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

基本 CRUD 操作
现在我们已经准备好并连接了数据库和项目,让我们使用 Quarkus 提供的默认 Mongo 客户端实现基本的 CRUD(创建、读取、更新、删除)操作。

定义实体
在本节中,我们将定义Article实体,代表 MongoDB 集合中的文档:

public class Article {
    @BsonId
    public ObjectId id;
    public String author;
    public String title;
    public String description;
    
    // getters and setters 
}

我们的类包含 id、author、title 和 description 字段。ObjectId是一种 BSON(JSON 的二进制表示)类型,用作 MongoDB 文档的默认标识符。@ BsonId注释将字段指定为 MongoDB 文档的标识符 ( _id )。

当应用于字段时,它表示该字段应映射到MongoDB 集合中的_id字段。使用这种组合,我们确保每个Article文档都有一个唯一的标识符,MongoDB 可以使用它来高效地索引和检索文档。

定义存储库
在本节中,我们将创建ArticleRepository类,使用MongoClient对Article实体执行 CRUD 操作。此类将管理与MongoDB数据库的连接,并提供创建、读取、更新和删除Article文档的方法。

首先,我们将使用依赖注入来获取MongoClient的实例:

@Inject
MongoClient mongoClient;

这使得我们无需手动管理连接即可与MongoDB数据库交互。

我们定义一个辅助方法getCollection()来从文章数据库中获取文章集合:

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

现在,我们可以使用集合提供程序执行基本的 CRUD 操作:

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

create ()方法将新的 Article 文档插入 MongoDB 集合。此方法使用insertOne()添加提供的文章对象,确保将其作为新条目存储在文章集合中。

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

listAll ()方法从 MongoDB 集合中检索所有 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 从集合中删除Article文档。它构造一个过滤器以匹配_id,并使用deleteOne删除与此过滤器匹配的第一个文档。

定义资源
作为一个简单的例子,我们将限制自己定义资源和存储库,而不实现服务层。

现在,我们需要做的就是创建资源,注入存储库,并为每个操作创建一个方法:

@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();
    }
}

测试我们的 API
为了确保我们的 API 正常工作,我们可以使用curl,这是一个使用各种网络协议传输数据的多功能命令行工具。

我们将向数据库添加一篇新文章。我们使用 HTTP POST 方法将代表文章的 JSON 有效负载发送到/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."
  }
]

将 Panache 与 MongoDB 结合使用
Quarkus 提供了一个名为Panache的额外抽象层,它简化了数据库操作并减少了样板代码。借助 Panache,我们可以将更多精力放在业务逻辑上,而较少关注数据访问代码。让我们看看如何使用 Panache 实现相同的 CRUD 操作。

Maven 依赖
要将 Panache 与 MongoDB 一起使用,我们需要添加quarkus-mongodb-panache依赖项:

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

定义实体
使用 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;
   
// getters and setters
}

定义存储库
使用 Panache,我们通过扩展PanacheMongoRepository来创建存储库。这为我们提供了 CRUD 操作,而无需编写样板代码:

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

扩展PanacheMongoRepository类时,可以使用几种常用方法来执行 CRUD 操作和管理 MongoDB 实体。现在,我们可以开箱即用persist()、listAll()或findById等方法。

定义资源
现在,我们需要做的就是创建使用新存储库的新资源,而无需所有样板代码:

@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();
    }
}

测试 API
我们还可以使用与其他示例中相同的curl命令来测试新的 API 。我们唯一要更改的是调用的端点,这次调用/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