Ktorでデータベースを使用したいので、com.takagimeow.infrastructure.database.dao
にDatabaseFactory
を実装してみます。
package com.takagimeow.infrastructure.database.dao import com.takagimeow.infrastructure.database.models.Users import kotlinx.coroutines.* import org.jetbrains.exposed.sql.* import org.jetbrains.exposed.sql.transactions.* import org.jetbrains.exposed.sql.transactions.experimental.* object DatabaseFactory { fun init() { val driverClassName = "org.postgresql.Driver" val jdbcURL = "jdbc:postgresql://localhost:5432/serverside" val user = "takagimeow" val password = "takagimeow_pass" val database = Database.connect( url = jdbcURL, driver = driverClassName, user = user, password = password ) transaction(database) { SchemaUtils.create(Users) } } suspend fun <T> dbQuery(block: suspend () -> T): T = newSuspendedTransaction(Dispatchers.IO) { block() } }
Application.ktで、このオブジェクトのinit()
メソッドを呼び出すことでデータベースへ接続を行います。
fun Application.module() { DatabaseFactory.init() ... }
そしてUsers
はDSLで定義します。
object Users : Table() { val id = integer("id").autoIncrement() val email = varchar("email", 128) val password = varchar("password", 128) val name = varchar("name", 128) val roleType = varchar("role_type", 128) override val primaryKey = PrimaryKey(id) }
このとき、ユーザーの作成に関するルートは公開したくないけども、初期データとしてユーザーレコードをテーブルに登録したい場合を考えてみました。
プロジェクトではKoinを使いたいのでUserDaoFacade
インターフェースを作成します。
package com.takagimeow.infrastructure.database.dao import com.takagimeow.infrastructure.database.models.* interface UserDAOFacade { suspend fun addNewUser(email: String, password: String, name: String): Unit }
そして、その実装であるUserDaoFacadeImpl
クラスを実装します。
package com.takagimeow.infrastructure.database.dao.impl import com.takagimeow.infrastructure.database.dao.UserDAOFacade import com.takagimeow.infrastructure.database.dao.DatabaseFactory.dbQuery import com.takagimeow.infrastructure.database.models.Users import kotlinx.coroutines.runBlocking import org.jetbrains.exposed.sql.* class UserDAOFacadeImpl : UserDAOFacade { override suspend fun addNewUser(email: String, password: String, name: String): Unit = dbQuery { val insertStatement = Users.insert { it[Users.email] = email it[Users.password] = password it[Users.name] = name it[roleType] = "USER" } insertStatement.resultedValues?.singleOrNull()?.let(::resultRowToUser) } }
実際は、各リポジトリでこのクラスを注入することでデータベースに対する操作を行なっていくのですが、今回はこのUserDAOFacadeImpl
を再利用してデータの挿入を行おうと思います。
com.takagimeow.infrastructure.database
パッケージにseed
パッケージを作成します。
このパッケージの中に、InserUser.kt
を作成します。
そしてmain()
を定義して、コードブロックの中でUserDaoFacadeImpl
クラスのaddNewUser()
を呼び出します。
package com.takagimeow.infrastructure.database.seed import com.takagimeow.infrastructure.database.dao.DatabaseFactory import com.takagimeow.infrastructure.database.dao.impl.UserDAOFacadeImpl suspend fun main() { DatabaseFactory.init() val dao = UserDAOFacadeImpl() dao.addNewUser( "takagimeow@example.com", "password", "takagi", ) }
あとは、IntelliJ IDEAで表示されているmain()
の横の実行ボタンを押すだけ。
ターミナルには次の様に表示されました。
2022-11-16 02:15:03.836 [DefaultDispatcher-worker-3] DEBUG Exposed - INSERT INTO users (email, "name", "password", role_type) VALUES ('takagimeow@example.com', 'takagi', 'password', 'USER') プロセスは終了コード 0 で終了しました
TablePlusを通してデータを確認してみました。ちゃんと登録されています。