... > Kotlin > Создание CRUD-приложения с...

Создание CRUD-приложения с использованием базы данных (Kotlin)

НАВИГАЦИЯ ПО СТРАНИЦЕ

Добавление зависимостей Определение сущности Инициализация базы данных Настройка Ktor-приложения

Для создания CRUD-приложения с использованием базы данных на Kotlin, мы можем воспользоваться фреймворком Ktor для веб-разработки и использовать SQLite в качестве базы данных для простоты.

Давайте создадим простое приложение, которое выполняет CRUD-операции (Create, Read, Update, Delete) для списка пользователей.

Добавление зависимостей:

Добавьте зависимости в файл build.gradle.kts:

plugins {
    kotlin("jvm") version "1.5.21"
    id("io.ktor.application") version "1.6.2"
    id("io.ktor.features") version "1.6.2"
    id("io.ktor.serialization") version "1.6.2"
}

repositories {
    mavenCentral()
}

dependencies {
    implementation(kotlin("stdlib"))
    implementation("io.ktor:ktor-server-netty:1.6.2")
    implementation("io.ktor:ktor-serialization:1.6.2")
    implementation("org.jetbrains.exposed:exposed-core:0.36.1")
    implementation("org.jetbrains.exposed:exposed-dao:0.36.1")
    implementation("org.jetbrains.exposed:exposed-jdbc:0.36.1")
    implementation("org.jetbrains.exposed:exposed-java-time:0.36.1")
    implementation("com.squareup.sqldelight:sqlite-driver:1.5.0")
    implementation("org.slf4j:slf4j-simple:1.7.32")
}

Определение сущности пользователя:

import org.jetbrains.exposed.dao.IntIdTable

data class User(val id: Int, val name: String, val email: String)

object Users : IntIdTable() {
    val name = varchar("name", 255)
    val email = varchar("email", 255)
}

Инициализация базы данных:

import org.jetbrains.exposed.dao.EntityID
import org.jetbrains.exposed.dao.IntEntity
import org.jetbrains.exposed.dao.IntEntityClass
import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.transactions.transaction

class UserRepository {
    fun getAllUsers(): List<User> {
        return transaction {
            Users.selectAll().map {
                User(it[Users.id].value, it[Users.name], it[Users.email])
            }
        }
    }

    fun getUserById(id: Int): User? {
        return transaction {
            Users.select { Users.id eq id }.singleOrNull()?.let {
                User(it[Users.id].value, it[Users.name], it[Users.email])
            }
        }
    }

    fun createUser(name: String, email: String): Int {
        return transaction {
            Users
                .returning(Users.id)
                .insertAndGetId {
                    it[Users.name] = name
                    it[Users.email] = email
                }.value
        }
    }

    fun updateUser(id: Int, name: String, email: String): Boolean {
        return transaction {
            Users.update({ Users.id eq id }) {
                it[Users.name] = name
                it[Users.email] = email
            } > 0
        }
    }

    fun deleteUser(id: Int): Boolean {
        return transaction {
            Users.deleteWhere { Users.id eq id } > 0
        }
    }
}

Настройка Ktor-приложения:

import io.ktor.application.*
import io.ktor.features.ContentNegotiation
import io.ktor.features.StatusPages
import io.ktor.http.HttpStatusCode
import io.ktor.jackson.jackson
import io.ktor.request.receive
import io.ktor.request.receiveOrNull
import io.ktor.response.respond
import io.ktor.routing.*
import io.ktor.server.engine.embeddedServer
import io.ktor.server.netty.Netty
import io.ktor.serialization.json

fun Application.module() {
    install(ContentNegotiation) {
        json()
    }

    install(StatusPages) {
        exception<Throwable> { cause ->
            call.respond(HttpStatusCode.InternalServerError, cause.localizedMessage)
        }
    }

    routing {
        val userRepository = UserRepository()

        route("/users") {
            get {
                call.respond(userRepository.getAllUsers())
            }
            post {
                val user = call.receive<User>()
                val userId = userRepository.createUser(user.name, user.email)
                call.respond(HttpStatusCode.Created, mapOf("id" to userId))
            }
        }

        route("/users/{id}") {
            get {
                val userId = call.parameters["id"]?.toIntOrNull()
                if (userId != null) {
                    val user = userRepository.getUserById(userId)
                    if (user != null) {
                        call.respond(user)
                    } else {
                        call.respond(HttpStatusCode.NotFound)
                    }
                } else {
                    call.respond(HttpStatusCode.BadRequest, "Invalid user ID format")
                }
            }
            put {
                val userId = call.parameters["id"]?.toIntOrNull()
                if (userId != null) {
                    val updatedUser = call.receiveOrNull<User>()
                    if (updatedUser != null) {
                        val success = userRepository.updateUser(userId, updatedUser.name, updatedUser.email)
                        if (success) {
                            call.respond(HttpStatusCode.OK)
                        } else {
                            call.respond(HttpStatusCode.NotFound)
                        }
                    } else {
                        call.respond(HttpStatusCode.BadRequest, "Invalid request body")
                    }
                } else {
                    call.respond(HttpStatusCode.BadRequest, "Invalid user ID format")
                }
            }
            delete {
                val userId = call.parameters["id"]?.toIntOrNull()
                if (userId != null) {
                    val success = userRepository.deleteUser(userId)
                    if (success) {
                        call.respond(HttpStatusCode.NoContent)
                    } else {
                        call.respond(HttpStatusCode.NotFound)
                    }
                } else {
                    call.respond(HttpStatusCode.BadRequest, "Invalid user ID format")
                }
            }
        }
    }
}

fun main() {
    embeddedServer(Netty, port = 8080, module = Application::module).start(wait = true)
}

В этом примере создано простое CRUD-приложение с использованием Ktor и SQLite. Вы можете выполнить следующие действия:

  • Получение всех пользователей: GET http://localhost:8080/users

  • Создание нового пользователя: POST http://localhost:8080/users с телом запроса в формате JSON.

  • Получение информации о пользователе по ID: GET http://localhost:8080/users/{id}

  • Обновление пользователя по ID: PUT http://localhost:8080/users/{id} с телом запроса в формате JSON.

  • Удаление пользователя по ID: DELETE http://localhost:8080/users/{id}.