Simplified MongoDB with Panache and Kotlin

MongoDB 是一个著名的 NoSQL 数据库,被广泛使用。MongoDB with Panache 在此熟悉框架之上提供了一层新功能。本指南不会深入讨论这两者的具体信息,因为这些信息已在 MongoDB with Panache guide中进行了讨论。在本指南中,我们将讨论在基于 Kotlin 的 Quarkus 应用程序中使用 MongoDB with Panache 所需的 Kotlin 特定更改。

First: an example

正如我们在 MongoDB with Panache 指南中所看到的,它允许我们在实体和存储库(也称为 DAO)中扩展功能,并添加一些自动提供的功能。使用 Kotlin 时,该方法与 Java 版本中的方法非常相似,只是有几个细微的改变。要为实体启用 Panache,可以像这样定义实体:

class Person: PanacheMongoEntity {
    lateinit var name: String
    lateinit var birth: LocalDate
    lateinit var status: Status
}

如您所见,我们的实体仍然简单。但是,与 Java 版本相比,有一个细微的差别。Kotlin 语言不支持与 Java 完全相同方式的静态方法。相反,我们必须使用 a companion object

class Person : PanacheMongoEntity() {
    companion object: PanacheMongoCompanion<Person> {  (1)
        fun findByName(name: String) = find("name", name).firstResult()
        fun findAlive() = list("status", Status.Alive)
        fun deleteStefs() = delete("name", "Stef")
    }

    lateinit var name: String  (2)
    lateinit var birth: LocalDate
    lateinit var status: Status
}
1 伴随对象保存所有与特定实例无关的方法,从而允许对绑定到特定类型的通用管理和查询。
2 此处有几个选项,但我们选择了 `lateinit`方式。通过这种方式,我们可以声明这些字段为非空,因为我们知道它们将通过构造函数(未显示)或 MongoDB POJO 编解码器从数据库加载数据得到正确分配。

这些类型与教程中提到的 Java 类型不同。对于 Kotlin 支持,所有 Panache 类型都可以在 `io.quarkus.mongodb.panache.kotlin`包中找到。此子包可以区分 Java 和 Kotlin 变体,并允许在单个项目中明确使用这两种变体。

在 Kotlin 版本中,我们只是将大部分 active record pattern功能移到了 companion object。除了这一细微改动,我们可以在世界 Java 端轻松映射的方式中使用我们的类型。

Using the repository pattern

Defining your entity

使用存储库模式时,可以将其实体定义为常规 POJO。

class Person {
    var id: ObjectId? = null; // used by MongoDB for the _id field
    lateinit var name: String
    lateinit var birth: LocalDate
    lateinit var status: Status
}

Defining your repository

使用存储库时,可以通过使存储库实现 `PanacheMongoRepository`以注入存储库,从而获得与活动记录模式中完全相同的方法:

@ApplicationScoped
class PersonRepository: PanacheMongoRepository<Person> {
     fun findByName(name: String) = find("name", name).firstResult()
     fun findAlive() = list("status", Status.Alive)
     fun deleteStefs() = delete("name", "Stef")
}

`PanacheMongoEntityBase`上定义的所有操作都在存储库上可用,因此使用存储库与使用活动记录模式完全相同,只不过需要注入存储库:

@Inject
lateinit var personRepository: PersonRepository

@GET
fun count() = personRepository.count()

Most useful operations

在编写完存储库后,以下是您将能够执行的最常见操作:

// creating a person
var person = Person()
person.name = "Stef"
person.birth = LocalDate.of(1910, Month.FEBRUARY, 1)
person.status = Status.Alive

// persist it: if you keep the default ObjectId ID field, it will be populated by the MongoDB driver
personRepository.persist(person)

person.status = Status.Dead;

// Your must call update() in order to send your entity modifications to MongoDB
personRepository.update(person);


// delete it
personRepository.delete(person);

// getting a list of all Person entities
val allPersons = personRepository.listAll()

// finding a specific person by ID
// here we build a new ObjectId, but you can also retrieve it from the existing entity after being persisted
ObjectId personId = new ObjectId(idAsString);
person = personRepository.findById(personId) ?: throw Exception("No person with that ID")

// finding all living persons
val livingPersons = personRepository.list("status", Status.Alive)

// counting all persons
val countAll = personRepository.count()

// counting all living persons
val countAlive = personRepository.count("status", Status.Alive)

// delete all living persons
personRepository.delete("status", Status.Alive)

// delete all persons
personRepository.deleteAll()

// delete by id
val deleted = personRepository.deleteById(personId)

// set the name of all living persons to 'Mortal'
var updated = personRepository.update("name", "Mortal").where("status", Status.Alive)

所有 list 方法都有等效的 stream 版本。

val persons = personRepository.streamAll();
val namesButEmmanuels = persons
    .map { it.name.toLowerCase() }
    .filter { it != "emmanuel" }

如需更多示例,请参阅 Java version以获取完整详细信息。除了针对 Kotlin 开发人员做了一些使操作更直观的 Kotlin 特定优化外,这两个 API 相同并且工作方式相同。这些优化包括更好地利用非空性以及 API 方法中缺少 Optional

Setting up and configuring MongoDB with Panache

要开始在 Kotlin 中使用 MongoDB with Panache,可以按照 Java 教程中列出的步骤进行操作。配置项目的最大变化是包含的 Quarkus 工件。当然,如果需要,可以保留 Java 版本,但如果只需要 Kotlin API,那么请包含以下依赖项:

pom.xml
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-mongodb-panache-kotlin</artifactId>  (1)
</dependency>
1 请注意末尾添加了 -kotlin。通常只需要此版本,但如果项目将使用 Java 和 Kotlin 代码,则可以安全地包含这两个工件。
build.gradle
implementation("io.quarkus:quarkus-mongodb-panache-kotlin") 1
1 请注意末尾添加了 -kotlin。通常只需要此版本,但如果项目将使用 Java 和 Kotlin 代码,则可以安全地包含这两个工件。