このページを編集

Simplified MongoDB with Panache and Kotlin

MongoDBは、広く利用されている有名なNoSQLデータベースです。MongoDB with Panacheは、このよく知られたフレームワークの上に新しいレイヤーを提供します。このガイドでは、MongoDB with 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 のように静的メソッドの概念をサポートしていません。その代わり、 コンパニオンオブジェクト を使わなければなりません。

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 の方法を選びました。これにより、これらのフィールドを非 null と宣言しておけば、 コンストラクタ (コードには表れていません) や 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
}

リポジトリの定義

リポジトリを使用する場合、 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版を参照してください。どちらのAPIも同じで、Kotlin開発者がより自然に感じられるようにKotlin特有の調整を行っている以外は、同じように動作します。これらの調整には、nullabilityの使用方法の改善や、APIメソッドに Optional を使用しないことなどが含まれます。

MongoDB with Panacheのセットアップと設定

MongoDB with PanacheをKotlinで使い始めるには、一般的には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の両方のコードを使用する場合は、両方のアーティファクト含めても大丈夫です。

関連コンテンツ