Introdução: Por que Kotlin e bancos de dados são a combinação ideal
Kotlin é uma linguagem moderna estaticamente tipada que roda sobre a JVM. Graças à sua sintaxe concisa, segurança contra nulos (null safety) e compatibilidade total com Java, Kotlin se tornou uma das linguagens que mais cresce para desenvolvimento backend. Neste artigo, vamos analisar como conectar e realizar operações CRUD com dois SGBDs populares: o relacional PostgreSQL e o orientado a documentos MongoDB.
Abordaremos duas abordagens principais: o uso da biblioteca Exposed para SQL e do framework KMongo para trabalhar com MongoDB. Todos os exemplos de código são escritos em Kotlin puro e estão prontos para execução.
1. Trabalhando com PostgreSQL através da biblioteca Exposed
1.1. Configuração de dependências
Para começar, adicione as seguintes dependências ao arquivo build.gradle.kts:
dependencies { implementation("org.jetbrains.exposed:exposed-core:0.44.0") implementation("org.jetbrains.exposed:exposed-dao:0.44.0") implementation("org.jetbrains.exposed:exposed-jdbc:0.44.0") implementation("org.postgresql:postgresql:42.6.0") implementation("com.zaxxer:HikariCP:5.0.1")}HikariCP é um pool de conexões de alto desempenho que usaremos para gerenciar as conexões com o banco de dados.
1.2. Conexão com o banco de dados
Vamos criar um objeto para gerenciar a conexão:
import com.zaxxer.hikari.HikariConfigimport com.zaxxer.hikari.HikariDataSourceimport org.jetbrains.exposed.sql.Database
object DatabaseFactory { fun init() { val config = HikariConfig().apply { driverClassName = "org.postgresql.Driver" jdbcUrl = "jdbc:postgresql://localhost:5432/my_db" username = "user" password = "password" maximumPoolSize = 10 isAutoCommit = false }
val dataSource = HikariDataSource(config) Database.connect(dataSource) }}1.3. Definição de tabelas e operações CRUD
Exposed usa um estilo DSL para descrever tabelas. Vamos definir uma tabela simples de usuários:
import org.jetbrains.exposed.sql.Tableimport org.jetbrains.exposed.sql.*import org.jetbrains.exposed.sql.transactions.transaction
object Users : Table() { val id = integer("id").autoIncrement() val name = varchar("name", 100) val email = varchar("email", 255).uniqueIndex()
override val primaryKey = PrimaryKey(id)}
// Inserção de dadosfun insertUser(name: String, email: String) { transaction { Users.insert { it[Users.name] = name it[Users.email] = email } }}
// Leitura de todos os usuáriosfun getAllUsers(): List<ResultRow> { return transaction { Users.selectAll().toList() }}
// Atualização de emailfun updateUserEmail(id: Int, newEmail: String) { transaction { Users.update({ Users.id eq id }) { it[email] = newEmail } }}
// Exclusão de usuáriofun deleteUser(id: Int) { transaction { Users.deleteWhere { Users.id eq id } }}1.4. Características do Exposed
- Transações: Todas as operações são executadas dentro do bloco
transaction. - Segurança de tipos: Erros em consultas SQL são detectados em tempo de compilação.
- Migrações: Exposed suporta a criação automática de tabelas através de
SchemaUtils.create(Users).
2. Trabalhando com MongoDB através do KMongo
2.1. Configuração de dependências
Adicione ao build.gradle.kts:
dependencies { implementation("org.litote.kmongo:kmongo-coroutine:4.9.0") implementation("org.litote.kmongo:kmongo-id:4.9.0")}<