์ง๋ ํฌ์คํ
https://rkdrkd-history.tistory.com/53
์ง๋ ํฌ์คํ ์์๋ ktor์์ http api๋ฅผ ๋ง๋ค์ด๋ณด๋ ๊ฒ์ ํ๋ค.
์ด๋ฒ ํฌ์คํ ์์๋ ktor์ database๋ฅผ ์ฌ์ฉํด data๋ฅผ ์ ์ฅํด ๋ณด๊ฒ ๋ค.
์ฝ๋๋ ์ง๋ ํฌ์คํ ์ ๋ฐํ์ผ๋ก ์ฌ๊ณต ํ ๊ฒ์ด๋ ์ด์ ๊ธ์ ๋ณด๊ณ ์ค๋ ๊ฒ์ ์ถ์ฒํ๋ค.
๋ฐ์ดํฐ๋ฒ ์ด์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ๋ค์ํ์ง๋ง
์ด ํฌ์คํ ์ ์ฌ์ฉํ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ Exposed์ h2database๋ฅผ ์ฌ์ฉํ๊ฒ ๋ค.
https://github.com/JetBrains/Exposed
https://github.com/h2 database/h2database
๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ถ๊ฐ
gradle.properties
exposed_version=0.41.1
h2_version=2.1.214
build.gradle.kts
val exposed_version: String by project
val h2_version: String by project
. . .
dependencies {
// exposed
implementation("org.jetbrains.exposed:exposed-core:$exposed_version")
implementation("org.jetbrains.exposed:exposed-dao:$exposed_version")
implementation("org.jetbrains.exposed:exposed-jdbc:$exposed_version")
// h2database
implementation("com.h2database:h2:$h2_version")
. . .
}
esposed, h2database ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ถ๊ฐํ๋ค.
Table ์์ฑ
Customer.kt
import org.jetbrains.exposed.sql.Table
object Customer: Table() {
val id = integer("id").autoIncrement()
val firstName = varchar("first_name", 10)
val lastName = varchar("last_name", 10)
override val primaryKey: PrimaryKey = PrimaryKey(id)
}
์ง๋ ์์ ๋ฅผ ๋ฐํ์ผ๋ก table์ ์์ฑํด ์ฃผ์๋ค.
- id: autoIncrement()๋ก ์๋์ผ๋ก ๊ฐ์ ํ ๋นํ๋ค.
- firstname๊ณผ lastname์ ํ๋๋ฅผ ์์ฑํด์ฃผ์๋ค.
- id๋ฅผ primary key๋ก ์ค์ ํ๋ค.
๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ฐ๊ฒฐ
๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ฐ๊ฒฐํ๋ ค๋ฉด ๋จผ์ h2 console์ ์ค์นํด์ผ ํ๋ค.https://h2database.com/html/main.html
h2 database ๊ณต์ ์ฌ์ดํธ์์ ์์ ์ ์ปดํจํฐ ์ด์ ์ฒด์ ์ ๋ง๋ database engine์ ์ค์นํ๋ค.
h2 database๋ฅผ ์ค์นํ ํ ํ์ผ javaw์ ์ฐพ์ ์ ์์ต๋๋ค ๋ผ๋ ์๋ฌ๊ฐ ๋ฌ๋ค๋ฉดjava๊ฐ ์ค์น๊ฐ ์ ๋ผ์๋ค๋ ๋ป์ด๋ฏ๋ก ์๋์ ์ฌ์ดํธ์ ๋ค์ด๊ฐ์ ์๋ฐ๋ฅผ ์ค์นํด ์ค๋ค.
https://www.java.com/ko/download/
java๋ฅผ ์ค์นํ๊ณ ๋๋ฉด jdk๋ ๊ฐ์ด ์์ฑ๋๋๋ฐ ๊ทธ๊ฒ์ ํ๊ฒฝ ๋ณ์๋ก ๋ฑ๋กํด ์ฃผ๋ ์์ ์ ํด์ผ ํ๋ค.
์๋ + R ๋๋ฅธ ํ ๋์ค๋ ์ฐฝ์ sysdm.cpl ,3 ์ ์ ๋ ฅํ๋ค.
๊ทธ๋ฆฌ๊ณ ํ๊ฒฝ ๋ณ์ ํญ์ ๋ค์ด๊ฐ์ ํ๊ฒฝ ๋ณ์๋ฅผ ์ค์ ํ๋ฉด ๋๋๋ฐ ์์ธํ ์ค๋ช ์ ์๋์ ๋ธ๋ก๊ทธ๋ฅผ ์ฐธ๊ณ ํ๊ธธ ๋ฐ๋๋ค.
์ฌ๊ธฐ๊น์ง ์๋ฃํ ํ ์๋์ฐ ํค๋ฅผ ๋๋ฌ h2 console์ ์คํํ๋ฉด...
๋ธ๋ผ์ฐ์ ์ ์ด๋ฐ ์ฐฝ์ด ๋จ๋ฉด ์ฑ๊ณต์ด๋ค.
๋ง์ด ์๋๋ฐ ์์ง ๋๋์ง ์์๋ค.
์ด์ ๋ ktor๋ก ๋์ด์์ database factory๋ฅผ ์์ฑํ๋ค.
package com.example.database
import com.example.models.Customer
import org.jetbrains.exposed.sql.Database
import org.jetbrains.exposed.sql.SchemaUtils
import org.jetbrains.exposed.sql.transactions.transaction
object DatabaseFactory {
fun init() {
val driverClassName = "org.h2.Driver"
val jdbcURL = "jdbc:h2:file:./build/db"
val database = Database.connect(jdbcURL, driverClassName)
transaction(database) {
SchemaUtils.create(Customer)
}
}
}
์ด ์ฝ๋์์ ์ฐ๋ฆฌ๊ฐ ๋ฐ๊ฟ์ผ ํ ๋ถ๋ถ์ jdbcURL ์ชฝ์ธ๋ฐ
h2 console์์ jdbc url์ด๋ผ๋ ์ ๋ ฅ ์ฐฝ์ด ์๋๋ฐ
jdbc:h2:~/์ํ๋ ์ด๋ฆ ์ ๋ ฅ
์ด๋ ๊ฒ database์ ์ด๋ฆ์ ์ค์ ํ๋ค.
์ด๋ฆ์ ์ค์ ํ๊ณ '์ฐ๊ฒฐ' ๋ฒํผ์ ๋๋ ์ ๋
๋ค์๊ณผ ๊ฐ์ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ฉด
์จ๊ฒจ์ง ์์ด์ฝ์์ ์ผ์ชฝ ์์ ์๋ icon์ ํด๋ฆญํด์ h2 ์ฝ์์ ์ฌ์คํํ ํ ๋ค์ ์๋ํ๋ฉด ์ ์์ ์ผ๋ก ์๋ํ๋ค.
๋ค์๊ณผ ๊ฐ์ ํ๋ฉด์ด ๋์ค๋ฉด ์ฑ๊ณต์ด๋ค.
์ ํ๋ฉด์ด ๋์ค๋ฉด
์ฌ์ฉ์ ํด๋์ ๋ค์๊ณผ ๊ฐ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ํ์ผ์ด ์์ฑ๋๋ค.
๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ๋ง๋ค์์ผ๋ ktor์์๋
val jdbcURL = "jdbc:h2:~/test"
jdbcURL์ ์์ ์ด ์์ฑํ database ์ด๋ฆ์ผ๋ก ๋ฐ๊พผ๋ค.
์ฟผ๋ฆฌ ์์ฑ
databaseFactory ํ์ผ ์์ ์ฟผ๋ฆฌ ํจ์๋ฅผ ๋ง๋ ๋ค.
suspend fun <T> dbQuery(block: suspend () -> T): T =
newSuspendedTransaction(Dispatchers.IO) { block() }
๊ทธ๋ฆฌ๊ณ dao ํ์ผ์ ๋ง๋ค์ด์ค๋ค.
DAOFacade.kt
package com.example.database
import com.example.models.Customers
interface DAOFacade {
suspend fun allCustomers(): List<Customers>
suspend fun customer(): Customers?
suspend fun addNewCustomer(firstName: String, lastName: String, email: String): Customers?
suspend fun editCustomer(id: Int, firstName: String, lastName: String, email: String): Boolean
suspend fun deleteCustomer(id: Int): Boolean
}
๋ฐ์ดํฐ๋ฒ ์ด์ค ๊ด๋ฆฌ์ ์ฌ์ฉ๋ ํจ์๋ค์ ์์ฑํด ์ค๋ค.
์ด์ DAOFacade ๊ตฌํ์ฒด๋ฅผ ๋ง๋ค์ด์ ๊ธฐ๋ฅ์ ๋ด์์ฃผ๋๋ก ํ๊ฒ ๋ค.
package com.example.database
import com.example.database.DatabaseFactory.dbQuery
import com.example.models.Customer
import com.example.models.Customers
import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
class DAOFacadeImpl: DAOFacade {
private fun resultRowToCustomer(row: ResultRow) = Customers(
id = row[Customer.id],
firstName = row[Customer.firstName],
lastName = row[Customer.lastName],
email = row[Customer.email]
)
override suspend fun allCustomers(): List<Customers> = dbQuery {
Customer.selectAll().map(::resultRowToCustomer)
}
override suspend fun customer(id: Int): Customers? = dbQuery {
Customer
.select { Customer.id eq id }
.map(::resultRowToCustomer)
.singleOrNull()
}
override suspend fun addNewCustomer(firstName: String, lastName: String, email: String): Customers? = dbQuery {
val insertStatement = Customer.insert {
it[Customer.firstName] = firstName
it[Customer.lastName] = lastName
it[Customer.email] = email
}
insertStatement.resultedValues?.singleOrNull()?.let(::resultRowToCustomer)
}
override suspend fun editCustomer(id: Int, firstName: String, lastName: String, email: String): Boolean = dbQuery {
Customer.update({ Customer.id eq id }) {
it[Customer.firstName] = firstName
it[Customer.lastName] = lastName
it[Customer.email] = email
} > 0
}
override suspend fun deleteCustomer(id: Int): Boolean = dbQuery {
Customer.deleteWhere { Customer.id eq id } > 0
}
}
์ด์ ๊ฐ ํจ์๋ค์ ์ญํ ์ ์์๋ณด์
- resultToRowCustomer ํจ์๋ ์ผ๋จ ์ ๋ชจ๋ฅด๊ฒ ์ง๋ง ๊ฐ customer item์ row์ ๋ฃ์ด์ฃผ๋ ๊ฒ์ผ๋ก ์ดํดํ๋ค.
- allCustomers ํจ์์์๋ db์ ์ ์ฅ๋ ๋ชจ๋ ๋ฐ์ดํฐ๋ฅผ ๋ถ๋ฌ์ค๊ฒ(selectAll()) ๋ง๋ค์๋ค.
- customer ํจ์๋ ํน์ id ๊ฐ์ ์ฐพ์์ parameter์ id์ customer์ id๊ฐ ๊ฐ์์ง(eq) ํ์ธํ๋ ์์ ์ ๊ฑฐ์ณ ๋ฐ์ดํฐ๋ฅผ ๋ถ๋ฌ์ค๊ฒ ํ๋ค.
- addNewCustomer ํจ์์์๋ insert๋ฅผ ์ฌ์ฉํด insertState(it)์ parameter์ ๋ฐ์ดํฐ๋ฅผ ๋ฃ์ด ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋ฃ์ด์ฃผ๋ ๋ก์ง์ผ๋ก ๊ตฌ์ฑํ๋ค.
- editCustomer ํจ์๋ update๋ฅผ ์ฌ์ฉํด customer ํจ์์ ๊ฐ์ด customer์ id๊ฐ ๊ฐ์์ง ํ์ธํ๋ ์์ ์ ๊ฑฐ์น ํ ์๋ก์ด ๋ฐ์ดํฐ๋ฅผ ๋ฃ์ด์ update ํ๋ ๋ก์ง์ด๋ค.
- deleteCustomer ํจ์๋ deleteWhere๋ฅผ ์ฌ์ฉํด id๊ฐ ๊ฐ์๊ฐ์ ์กฐ๊ฑด์ ์์ฑํด true์ธ ๊ฒฝ์ฐ๋ง ๊ฐ์ ์ญ์ ์ํค๋ ๋ก์ง์ ๋ง๋ค์๋ค.
์ง๊ธ ๊ธ์ ์ ๋ค๊ฐ ์์ด ๋ง์์ ธ์ ์ผ๋จ ์ฌ๊ธฐ๊น์ง ํ๋๋ก ํ๊ฒ ๋ค.
๋ค์ ํฌ์คํ ์ ์์ ๊ธ์์ ํ๋ ์ฝ๋๋ค์ ์ด์ฉํด ๊ธฐ์กด์ api๋ฅผ ์์ ํด ๋ณด๋๋ก ํ๊ฒ ๋ค.
'๐ | ๊ธฐํ ๊ธฐ์ > ๐ฅ๏ธ | Ktor' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Kotlin, Ktor] ktor๋ก http api ๋ง๋ค๊ธฐ(2) (0) | 2023.06.14 |
---|---|
[Kotlin, Ktor] ktor ํ๋ก์ ํธ ์์ํ๊ธฐ(1) (4) | 2023.06.12 |