Usando a Biblioteca Exposed
Lissa Ferreira
Posted on September 27, 2021
Kotlinautas
Esse conteúdo é oferecido e distribuído pela comunidade Kotlinautas, uma comunidade brasileira que busca oferecer conteúdo gratuito sobre a linguagem Kotlin em um espaço plural.
O quê é um ORM?
ORM (Mapeamento de Objeto Relacional) é uma maneira de mapear dados de um banco de dados, em objetos de uma aplicação. Como se fosse uma ponte entre classes da nossa aplicação, e o banco de dados da aplicação.
ORM's servem principalmente para facilitar a comunicação entre uma aplicação e seu banco de dados. Facilitando processos de leitura, escrita, atualização e remoção de dados.
O quê é Exposed?
Exposed é a biblioteca oficial de ORM para Kotlin, criada pela própria JetBrains. Uma de suas principais vantagens é poder usar diferentes bancos de dados, e poder trocar qual banco você está usando de maneira fácil. A lista de bancos de dados atualmente suportada pelo Exposed é:
- H2
- MySQL
- MariaDB
- Oracle
- PostgreSQL
- SQL Server
- SQLite
O quê vamos criar?
Vamos criar um sistema de cadastro de planetas. Onde poderemos inserir informações sobre um planeta, e essas informações serão inseridas em um banco de dados. Com isso, poderemos usar a Exposed para conectar a nossa aplicação, á um banco de dados que desejarmos.
Criando o projeto
Abra seu IntelliJ no menu inicial e clique em New Project:
Depois, selecione a opção Kotlin DSL build script, selecione também a opção Kotlin/JVM, e opicionalmente remova a primeira opção Java. Essa opção não vai mudar em nada, pois ela dá suporte do Gradle á linguagem Java, mas apenas iremos usar Kotlin.
Após isso, clique em Next e escreva o nome do projeto e a localização na sua máquina. Essas duas opção são completamente pessoais, caso não tenha nenhuma ideia, coloque algo como exposed apenas como identificação.
Agora, com o projeto aberto, vá ao aquivo build.gradle.kts
e adicione as dependências da Exposed, com a seção dependencies
ficando assim:
dependencies {
implementation(kotlin("stdlib"))
implementation("org.jetbrains.exposed:exposed-core:0.33.1")
implementation("org.jetbrains.exposed:exposed-dao:0.33.1")
implementation("org.jetbrains.exposed:exposed-jdbc:0.33.1")
implementation("com.h2database:h2:1.4.199")
implementation("org.slf4j:slf4j-api:1.7.5")
implementation("org.slf4j:slf4j-simple:1.6.4")
}
Agora, clique no elefante no canto superior direito para carregar as alterações no Gradle.
Após isso, poderemos começar a programar. Você pode criar um arquivo em src/main/kotlin/
chamado main.kt
para ser o arquivo principal da aplicação.
Mas com qualquer nome de arquivo, como você irá usar a Exposed, sempre se lembre de importar a Exposed no começo do arquivo:
import org.jetbrains.exposed.sql.*
Usando a Exposed
Primeiro, vamos precisar criar um objeto que irá representar uma tabela em nosso banco de dados, e dentro desse objeto inserir as colunas do nosso banco (como propriedades). Isso pode ser feito da seguinte maneira:
import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.transactions.transaction
object Planetas: Table(){
val nome = varchar("nome", 30)
val massa = double("massa")
val solido = bool("solido")
}
- Usamos a palavra
object
para criar o objeto, colocamos o nome da tabelaPlanetas
, e o tipo da variável, que é um tipo da Exposed, SendoTable
; - Dentro do objeto, criamos três variáveis, sendo
nome
,massa
, esolido
.nome
irá guardar o nome do planeta,massa
irá guardar a massa do planeta comparada á terra esolido
irá determinar se o planeta é sólido ou não; - Para determinar essas variáveis, usamos tipos de dados de um banco de dados, como
varchar
,double
, ebool
;
Após isso, podemos criar a nossa função main
. Dentro dela, vamos primeiramente conectar ao banco de dados. Isso pode ser feito com a função Database.connect
dessa maneira:
...
fun main(){
Database.connect("jdbc:h2:mem:regular;DB_CLOSE_DELAY=-1;", "org.h2.Driver")
}
- Estamos usando o banco de dados H2. Um banco de dados Java, que pode funcionar apenas na memória. Vamos usar esse banco de dados pois a cada vez que rodarmos o programa, teremos um novo banco totalmente zerado. Com isso você ficará livre para testar o banco, criando, lendo, editando e removendo dados;
- Para fazer essa conexão, tivemos que passar um texto que representa esse banco. Caso você queira mudar o banco, você apenas irá precisar mudar esse texto;
Agora precisamos inserir a tabela Planetas
que criamos no banco. Isso pode ser feito de maneira completamente automática usando a função SchemaUtils.create
. Essa função pode ser usada da seguinte maneira:
...
fun main(){
Database.connect("jdbc:h2:mem:regular;DB_CLOSE_DELAY=-1;", "org.h2.Driver")
transaction {
SchemaUtils.create(Planetas)
}
}
- Usamos um bloco
transaction
pois toda conexão ao banco (escrita, leitura, edição e remoção) precisa estar dentro de um blocotransaction
; - Passamos ao
SchemaUtils.create
o nosso objetoPlanetas
. Com isso, essa tabela será criada no banco de dados;
Agora, vamos criar um bloco while (true)
onde iremos executar um mesmo trecho de código eternamente, onde iremos ler o nome, massa e se o planeta é sólido ou não, vamos enviar esses dados ao banco de dados, e também mostrar todas as linhas do banco na tela.
...
fun main(){
Database.connect("jdbc:h2:mem:regular;DB_CLOSE_DELAY=-1;", "org.h2.Driver")
transaction {
SchemaUtils.create(Planetas)
}
while (true){
}
}
Agora vamos usar a função readLine
para pegar os dados da linha de comando, mostrando na tela pergunta por pergunta:
...
fun main(){
Database.connect("jdbc:h2:mem:regular;DB_CLOSE_DELAY=-1;", "org.h2.Driver")
transaction {
SchemaUtils.create(Planetas)
}
while (true){
print("Insira o nome do planeta: ")
val nomePlaneta = readLine().toString()
print("Insira a massa do planeta: ")
val massaPlaneta = readLine().toString().toDouble()
print("O planeta é sólido? [sim/não]: ")
val solidoPlaneta = readLine() == "sim"
}
}
- na variável
nomePlaneta
apenas transformamos o texto escrito na linha de comando emString
com.toString()
; - na variável
massaPlaneta
primeiro transformamos o texto escrito emString
, e depois transformamos essaString
emDouble
. Para assim obtermos o número decimal da massa do planeta em relação á terra; - na variável
solidoPlaneta
testamos se o texto escrito é igual á "sim". se essa condição for verdadeira, o planeta é sólido. Se não, o planeta não é sólido;
Agora vamos executar a transação para inserirmos esses dados no banco:
...
fun main(){
Database.connect("jdbc:h2:mem:regular;DB_CLOSE_DELAY=-1;", "org.h2.Driver")
transaction {
SchemaUtils.create(Planetas)
}
while (true){
print("Insira o nome do planeta: ")
val nomePlaneta = readLine().toString()
print("Insira a massa do planeta: ")
val massaPlaneta = readLine().toString().toDouble()
print("O planeta é sólido? [sim/não]: ")
val solidoPlaneta = readLine() == "sim"
transaction {
Planetas.insert {
it[nome] = nomePlaneta
it[massa] = massaPlaneta
it[solido] = solidoPlaneta
}
}
}
}
- Para inserirmos esses dados, podemos usar a função
Planetas.insert
, informando o valor de cada coluna do banco comit[COLUNA] = valor
.
Agora já conseguimos escrever dados no banco. Por fim, vamos pegar todos os dados do banco, e mostrar na tela. Mostrando que realmente conseguimos escrever os dados. Primeiro, vamos pegar todas as linhas da tabela Planetas
:
...
fun main(){
Database.connect("jdbc:h2:mem:regular;DB_CLOSE_DELAY=-1;", "org.h2.Driver")
transaction {
SchemaUtils.create(Planetas)
}
while (true){
print("Insira o nome do planeta: ")
val nomePlaneta = readLine().toString()
print("Insira a massa do planeta: ")
val massaPlaneta = readLine().toString().toDouble()
print("O planeta é sólido? [sim/não]: ")
val solidoPlaneta = readLine() == "sim"
transaction {
Planetas.insert {
it[nome] = nomePlaneta
it[massa] = massaPlaneta
it[solido] = solidoPlaneta
}
}
transaction {
val planetasSalvos = Planetas.selectAll()
}
}
}
Agora vamos percorrer por todo essa lista de dados, e mostrar na tela planeta por planeta usando um .map
:
...
fun main(){
Database.connect("jdbc:h2:mem:regular;DB_CLOSE_DELAY=-1;", "org.h2.Driver")
transaction {
SchemaUtils.create(Planetas)
}
while (true){
print("Insira o nome do planeta: ")
val nomePlaneta = readLine().toString()
print("Insira a massa do planeta: ")
val massaPlaneta = readLine().toString().toDouble()
print("O planeta é sólido? [sim/não]: ")
val solidoPlaneta = readLine() == "sim"
transaction {
Planetas.insert {
it[nome] = nomePlaneta
it[massa] = massaPlaneta
it[solido] = solidoPlaneta
}
}
transaction {
val planetasSalvos = Planetas.selectAll()
planetasSalvos.map {
if (it[Planetas.solido]){
println("Planeta ${it[Planetas.nome]} tem ${it[Planetas.massa]} massas terrestres e é sólido")
}else{
println("Planeta ${it[Planetas.nome]} tem ${it[Planetas.massa]} massas terrestres e não é sólido")
}
}
}
}
}
- Dentro de um
map
, percorrermos elemento por elemento, e para nos referirmos ao elemento atual, podemos usar a variávelit
. e dentro desseit
podemos pegar os valores de cada linha, podendo assim mostrar na tela;
Agora, executando esse programa, poderemos ver na prática como criamos um código que pode inserir e ler dados de maneira dinâmica:
Insira o nome do planeta: Mercúrio
Insira a massa do planeta: 0.1
O planeta é sólido? [sim/não]: sim
Planeta Mercúrio tem 0.1 massas terrestres e é sólido
Insira o nome do planeta: Vênus
Insira a massa do planeta: 0.9
O planeta é sólido? [sim/não]: sim
Planeta Mercúrio tem 0.1 massas terrestres e é sólido
Planeta Vênus tem 0.9 massas terrestres e é sólido
Update e Delete
Duas operações que não usamos foram a Updatee Delete. Essas duas são muito parecidas em seu uso na Exposed. Pois nas duas é (quase sempre) necessário usar um parâmetro WHERE
para definir quais linhas desejamos mudar/remover. Por exemplo, podemos fazer um Update com WHERE colocando a condição como argumento da função, e a alteração em si no corpo. Dessa maneira:
transaction {
Planetas.update({ Planetas.nome eq "teste" }){
it[Planetas.nome] = "Vênus"
}
}
- Colocamos a condição entre
{}
como argumento da função, e no corpo alteramos a linha diretamente;
E para o Delete podemos fazer a mesma coisa, mas agora apenas precisamos colocar a condição:
transaction {
Planetas.deleteWhere { Planetas.nome eq "teste" }
}
Usando outros bancos de dados
Caso você queira usar os outros bancos de dados que a Exposed suporta, você pode ver a lista de URL's de conexão de diferentes bancos. Essa lista pode ser acessada clicando aqui
Finalização
Nesse artigo você aprendeu como usar de forma básica a biblioteca Exposed, para escrever, ler, editar e remover dados de um banco.
Muito obrigada por ler ❤️🏳️⚧️ e me segue nas redes, é tudo @lissatransborda 👀
Posted on September 27, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.