Simplified MongoDB with Panache and Kotlin

MongoDB是一个众所周知的NoSQL数据库,被广泛使用。MongoDB与Panache在这个熟悉的框架之上提供了一个新的层次。本指南将不深入讨论这两者的具体细节,因为这些内容已经在 MongoDB with Panache指南 中涵盖。在本指南中,我们将介绍在基于Kotlin的Quarkus应用程序中使用MongoDB with Panache所需的Kotlin特定变化。

第一:一个例子

正如我们在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那样支持静态方法的概念。相反,我们必须使用一个 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 companion object持有所有与特定实例无关的方法,允许进行一般管理和与特定类型绑定的查询。
2 这里有一些选项,但我们选择了 lateinit 的方法。这允许我们将这些字段声明为非空,因为我们知道它们会被构造函数(未显示)或从数据库加载数据的MongoDB POJO编解码器正确分配。
These types differ from the Java types mentioned in those tutorials. For Kotlin support, all the Panache types will be found in the io.quarkus.mongodb.panache.kotlin package. This subpackage allows for the distinction between the Java and Kotlin variants and allows for both to be used unambiguously in a single project.

在Kotlin版本中,我们只是把大部分的功能 active record pattern 转移到了 companion object 。除了这个细微的变化,我们还可以从 Java 方面轻松映射的方式来处理我们的类型。

使用资源库模式

定义你的实体

当使用存储库模式时,你可以将你的实体定义为普通的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
}

定义你的存储库

当使用 Repositories 时,你可以得到与活动记录模式完全相同的方便方法,注入到你的 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 上定义的操作都可以在你的版本库上使用,所以使用它与使用active record(活动记录)模式完全一样,只是你需要注入它。

@Inject
lateinit var personRepository: PersonRepository

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

最有用的操作

编写存储库后,您可以执行以下最常见的操作:

// 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版本 以获取完整详细信息。除了一些针对Kotlin的调整以使Kotlin开发者感觉更自然外,两个API都是一样的,工作方式也是一样的。这些调整包括更好地使用nullability和API方法上缺乏 Optional

使用 Panache 设置和配置 MongoDB

要开始使用带有 Kotlin 的 Panache 的 MongoDB,您通常可以按照 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 代码,你可以安全地包含这两个工件。