MongoDB simplificado con Panache y Kotlin
MongoDB es una base de datos NoSQL muy conocida y ampliamente utilizada. MongoDB con Panache ofrece una nueva capa sobre este marco familiar. Esta guía no se adentrará en los detalles de ninguna de las dos, ya que estos están cubiertos en la guía de MongoDB con Panache. En esta guía, cubriremos los cambios específicos de Kotlin necesarios para usar MongoDB con Panache en tus aplicaciones Quarkus basadas en Kotlin.
Primero: un ejemplo
Como vimos en la guía MongoDB with Panache, nos permite extender la funcionalidad en nuestras entidades y repositorios (también conocidos como DAOs) con alguna funcionalidad proporcionada automáticamente. Cuando se utiliza Kotlin, el enfoque es muy similar a lo que vemos en la versión Java con un ligero cambio o dos. Para habilitar tu entidad con Panache, la definirías algo así como:
class Person: PanacheMongoEntity {
lateinit var name: String
lateinit var birth: LocalDate
lateinit var status: Status
}
Como puede ver, nuestras entidades siguen siendo simples. Sin embargo, hay una pequeña diferencia con la versión de Java. El lenguaje Kotlin no soporta la noción de métodos estáticos de la misma manera que Java. En su lugar, debemos utilizar un objeto acompañante:
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 | El objeto complementario contiene todos los métodos no relacionados con una instancia específica, lo que permite la gestión general y la consulta vinculada a un tipo específico. |
2 | Aquí hay opciones, pero hemos elegido el enfoque de lateinit . Esto nos permite declarar estos campos como no nulos sabiendo que serán asignados apropiadamente ya sea por el constructor (no mostrado) o por el codec POJO de MongoDB cargando datos de la base de datos. |
Estos tipos difieren de los tipos Java mencionados en esos tutoriales. Para el soporte de Kotlin, todos los tipos de Panache se encontrarán en el paquete io.quarkus.mongodb.panache.kotlin . Este subpaquete permite distinguir entre las variantes de Java y Kotlin y permite utilizar ambas de forma inequívoca en un mismo proyecto.
|
En la versión de Kotlin, simplemente hemos trasladado la mayor parte de la funcionalidad de active record pattern
a la página companion object
. Aparte de este ligero cambio, podemos trabajar con nuestros tipos de forma que se pueda mapear fácilmente desde el lado Java del mundo.
Uso del patrón de repositorio
Definir su entidad
Cuando se utiliza el patrón de repositorio, se pueden definir las entidades como POJO normales.
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
}
Definir el repositorio
Cuando se utilizan Repositorios, se obtienen exactamente los mismos métodos convenientes que con el patrón de registro activo, inyectados en su Repositorio, haciendo que implementen 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")
}
Todas las operaciones que se definen en PanacheMongoEntityBase
están disponibles en su repositorio, por lo que utilizarlo es exactamente igual que utilizar el patrón de registro activo, excepto que hay que inyectarlo:
@Inject
lateinit var personRepository: PersonRepository
@GET
fun count() = personRepository.count()
Operaciones más útiles
Una vez que haya escrito su repositorio, estas son las operaciones más comunes que podrá realizar:
// 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)
Todos los métodos de list
tienen versiones equivalentes de stream
.
val persons = personRepository.streamAll();
val namesButEmmanuels = persons
.map { it.name.toLowerCase() }
.filter { it != "emmanuel" }
Para más ejemplos, consulta la versión de Java para ver los detalles completos. Ambas APIs son iguales y funcionan de forma idéntica, excepto por algunos ajustes específicos de Kotlin para que las cosas resulten más naturales para los desarrolladores de Kotlin. Estos ajustes incluyen cosas como un mejor uso de la anulabilidad y la ausencia de Optional
en los métodos de la API.
Instalación y configuración de MongoDB con Panache
Para empezar a usar MongoDB con Panache con Kotlin, puedes, generalmente, seguir los pasos establecidos en el tutorial de Java. El mayor cambio en la configuración de tu proyecto es el artefacto de Quarkus a incluir. Puedes, por supuesto, mantener la versión Java si lo necesitas pero si todo lo que necesitas son las APIs de Kotlin entonces incluye la siguiente dependencia en su lugar:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-mongodb-panache-kotlin</artifactId> (1)
</dependency>
1 | Observa la adición de -kotlin al final. Generalmente solo necesitarás esta versión, pero si tu proyecto va a utilizar tanto código Java como Kotlin, puedes incluir ambos artefactos de forma segura. |
implementation("io.quarkus:quarkus-mongodb-panache-kotlin") (1)
1 | Observa la adición de -kotlin al final. Generalmente solo necesitarás esta versión, pero si tu proyecto va a utilizar tanto código Java como Kotlin, puedes incluir ambos artefactos de forma segura. |