Ktor練功場#3筆記-使用Exposed資料庫

YungHsin
9 min readAug 24, 2020

--

本次練功坊學習重點:

教你在Ktor專案學會使用Exposed來串接資料庫功能!

什麼是Exposed呢?

是一種ORM資料庫的框架,提供用兩種方式來存取資料庫,一種用SQL DSL去寫,另一種就是這次練功使用的DAO方式來寫,在後面解說實作部分就能看見了。

官網介紹連結: https://github.com/JetBrains/Exposed

支援的資料庫類型也很多,一般常用的MySQL,PostgreSQL都有支援,這次練習主要目的是讓大家簡單上手,所以挑選了H2的這種In-Memory資料庫使用,比較其他類型的資料庫需要比較多的安裝前置作業,H2只要在專案設定library後就,就能立即開始寫Code使用了。

H2的介紹: https://www.h2database.com/html/main.html

專案設定

(1)開新專案

新的專案設定還是老樣子選擇Ktor,Client Templating 勾選CSS DSL, Server HttpClient Engine勾選Apache HttpClient Engine,ContentNegotiation勾選Jackson。

(2)加入Exposed Library

再來的步驟需要手動來填資料了,因為IntelliJ開新專案建立時並沒有Expoese Library的套件可以預先勾選設定,所以要先到build.gradle的檔案裡加入以下三行的dependencies:

implementation "org.jetbrains.exposed:exposed-core:0.24.1"
implementation "org.jetbrains.exposed:exposed-dao:0.24.1"
implementation "org.jetbrains.exposed:exposed-jdbc:0.24.1"

(3)加入H2 Library

接下來就是需要建立連線來存取H2資料庫,所以也需要加入套件

implementation "com.h2database:h2:1.4.199"

填好就長得像以下的build.gradle截圖了

資料表跟資料格式的定義

這次幾乎是拿官網的範例來做練習,主要是目的是存取使用者跟居住的城市的資料。因此資料存取的部分會需要兩部分:

(1)建立Table所需的資料表

使用者Users跟居住城市Cities

object Users : IntIdTable() {
val name = varchar("name", 50).index()
val city = reference("city", Cities)
val age = integer("age")
}
object Cities: IntIdTable() {
val name = varchar("name", 50)
}

(2)定義資料格式DAO

Table建立好後,需要有對應的物件來存取,所以Users跟Citites的類別也需要寫進來

class User(id: EntityID<Int>) : IntEntity(id) {
companion object : IntEntityClass<User>(Users)

var name by Users.name
var city by City referencedOn Users.city
var age by Users.age
}

class City(id: EntityID<Int>) : IntEntity(id) {
companion object : IntEntityClass<City>(Cities)

var name by Cities.name
val users by User referrersOn Users.city
}

與H2資料庫進行連線

以上資料建立好後,就在Application.kt裡加入跟H2資料庫連線的這一行程式,特別注意的是,如果不想每次呼叫API時,資料庫就被清空重來,我們需要加上DB_CLOSE_DELAY=-1這個參數

Database.connect("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1", driver = "org.h2.Driver", user = "root", password = "")

建立資料庫Table並產生資料

透過Exposed Library,資料庫的建立,讀取,更新,刪除這些動作(所謂的CRUD),都能透過transaction實作出來。

Transcation介紹: https://github.com/JetBrains/Exposed/wiki/Transactions

transaction {

SchemaUtils.create(Cities, Users)
val taipeiCity = City.new {
name = "Taipei"
}
val hischuCity = City.new {
name = "HisnChu"
}

User.new {
name = "demo"
city = taipeiCity
age = 666
}

User.new {
name = "yaya"
city = hischuCity
age = 777
}
}

(1)SchemaUtils.create (Cities, Users)意思就是將一開始定義的object Users跟object Cities建立出Table。

(2)City.new{name=”Tapipei”}跟City.new{name=”HisnChu”}就是建立兩筆City的資料。

(3) User.new{ name = “demo”, city = taipeiCity, age = 666}跟User.new { name = “yaya” city = hischuCity age = 777 }就是建立兩筆User資料。

取得資料庫裡Table裡頭的資料

同樣要去資料庫撈出剛剛建立的資料,我們一樣要透過在transaction去進行讀取的動作,只要呼叫User.all()就能將存在User Table的資料提取。

val users = transaction {
User.all().joinToString { "user:${it.name} city:${it.city.name} age:${it.age}"}
}

透過Http Request來測試

分別寫一個generate-user跟get-user API來試試看

generate-user

get("/generate-user"){
transaction {

SchemaUtils.create(Cities, Users)
val taipeiCity = City.new {
name = "Taipei"
}
val hischuCity = City.new {
name = "HisnChu"
}

User.new {
name = "demo"
city = taipeiCity
age = 666
}

User.new {
name = "yaya"
city = hischuCity
age = 777
}
}

call.respondText("generate-user success", contentType = ContentType.Text.Plain)
}

get-user

get("/get-user") {

val users = transaction {
User.all().joinToString { "user:${it.name} city:${it.city.name} age:${it.age}"}
}
call.respondText(users, contentType = ContentType.Text.Plain)

}

把以上程式都寫好後,記得執行專案,跑起來後,用瀏覽器連到 http://0.0.0.0:8080/generate-user,若成功就會回傳success!

接著瀏覽器連到 http://0.0.0.0:8080/get-user,就能讀取由generate-user產生的兩筆資料了

以上就是Ktor練功場#3的內容,教你快速入門使用Exposed來串接資料庫!

歡迎各位也一起來練功場學習Ktor囉!

2020–07–26~2020–09–20相約在線上! 隔週一起來練功!

https://tw.kotlin.tips/dojos/ktortw

--

--

YungHsin
YungHsin

No responses yet