本次練功坊學習重點:
教你在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相約在線上! 隔週一起來練功!