Kotlin

Exposed 기초

dongb 2024. 1. 4. 17:23
반응형

개요

Exposed ORM은 Kotlin으로 작성된 ORM(Object-Relational Mapping) 라이브러리로, SQL Query를 작성하는 대신 Kotlin 코드로 데이터베이스를 조작할 수 있게 해줍니다.
이 글에서는 Exposed ORM을 사용하여 One-to-Many 관계의 엔티티를 생성하고 CRUD를 구현하는 방법, 그리고 Join read를 구현하는 방법에 대해 알아보겠습니다.
 

One-to-Many 관계의 엔티티 생성 방법

One-to-Many 관계란, 한 엔티티가 다른 엔티티를 여러 개 가지는 관계입니다. 예를 들어, 한 사용자(User)가 여러 개의 주소(Address)를 가지는 경우, 사용자(User)와 주소(Address)는 One-to-Many 관계를 가집니다.
다음 예시를 통해 One-to-Many 관계의 엔티티를 생성하는 방법을 알아보겠습니다. 예시로는 User 엔티티와 Address 엔티티가 있고, User 엔티티는 여러 개의 Address 엔티티를 가지는 One-to-Many 관계를 가지고 있다고 가정합니다.

User 테이블 생성

object Users : Table() {
    val id = integer("id").autoIncrement().primaryKey()
    val name = varchar("name", 50)
}

Address 테이블 생성

object Addresses : Table() {
    val id = integer("id").autoIncrement().primaryKey()
    val street = varchar("street", 255)
    val city = varchar("city", 50)
    val user_id = (integer("user_id") references Users.id).nullable()
}

위의 코드에서 user_id 열은 Users 테이블의 id 열을 참조합니다.

User 엔티티와 Address 엔티티 생성

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

    var name by Users.name
    val addresses by Address referrersOn Addresses.user_id
}

class Address(id: EntityID<Int>) : IntEntity(id) {
    companion object : IntEntityClass<Address>(Addresses)

    var street by Addresses.street
    var city by Addresses.city
    var user by User optionalReferencedOn Addresses.user_id
}

위의 코드에서 val addresses by Address referrersOn Addresses.user_id는 User 엔티티가 Address 엔티티를 여러 개 가질 수 있도록 하는 코드입니다.

var user by User optionalReferencedOn Addresses.user_id는 Address 엔티티가 User 엔티티를 참조할 수 있도록 하는 코드입니다.

CRUD 구현 방법

데이터를 생성(Create), 조회(Read), 수정(Update), 삭제(Delete)하는 CRUD 작업을 구현하는 방법에 대해 알아보겠습니다.

데이터 생성

transaction {
    val user = User.new {
        name = "John"
    }
    Address.new {
        street = "123 Main St"
        city = "Anytown"
        this.user = user
    }
}

위의 코드에서 User.newAddress.new를 사용하여 새로운 User 엔티티와 Address 엔티티를 생성합니다.

Address 엔티티의 user 프로퍼티를 User 엔티티로 설정하여 One-to-Many 관계를 설정합니다.

데이터 조회

val user = User.findById(1)
user?.addresses?.forEach {
    println("${it.street}, ${it.city}")
}

 

데이터 수정

transaction {
    val user = User.findById(1)
    user?.name = "Jane"
}

 

데이터 삭제

transaction {
    val user = User.findById(1)
    user?.addresses?.forEach {
        it.delete()
    }
    user?.delete()
}

Join read 구현 방법

Join read란, 두 개 이상의 테이블을 조인해서 조회하는 방법입니다. Exposed ORM에서는 innerJoin, leftJoin, crossJoin 등의 메서드를 사용하여 Join read를 구현할 수 있습니다.

transaction {
    (Users innerJoin Addresses)
        .slice(Users.name, Addresses.street, Addresses.city)
        .select { Users.id eq Addresses.user_id }
        .forEach {
            println("${it[Users.name]}: ${it[Addresses.street]}, ${it[Addresses.city]}")
        }
}

위의 코드에서 Users와 Addresses를 innerJoin하여 조인을 수행합니다. slice 메서드는 Users.name, Addresses.street, Addresses.city 열만 선택하여 조회하도록 설정합니다. select 메서드는 Users.idAddresses.user_id가 일치하는 행들을 선택합니다. 선택된 결과를 forEach를 사용하여 출력합니다.

위와 같이 Exposed ORM을 사용하여 One-to-Many 관계의 엔티 티를 생성하고 CRUD를 구현하며, Join read를 구현할 수 있습니다.

반응형