Kotlin으로 Spring Boot 시작해보기-2

문지은·2021년 9월 13일
0

코틀린 스프링 부트 서버 구성을 이어서 진행해보자.

JPA 연결

build.gradle.kts에 플러그인을 추가해서 lazy fetching이 가능하도록 한다. 이로 인해서 @Entity 어노테이션이 추가된 오브젝트는 lazy fetching을 할 수 있다.

plugins {
    id("org.springframework.boot") version "2.5.4"
    id("io.spring.dependency-management") version "1.0.11.RELEASE"
    kotlin("jvm") version "1.5.21"
    kotlin("plugin.spring") version "1.5.21"
    kotlin("plugin.jpa") version "1.5.21"
    // 여기 새로 추가
    kotlin("plugin.allopen") version "1.4.32"
}

// allOpen 정의
allOpen {
    annotation("javax.persistence.Entity")
    annotation("javax.persistence.Embeddable")
    annotation("javax.persistence.MappedSuperclass")
}

lazy-fetching(지연 로딩)이란?
필요한 정보만 가져오고 필요하지 않은 정보는 프록시를 이용하여 가져오는 방식. 예를 들면 밑의 Article Entity 코드에서 Article을 조회할 경우 필요하지 않으면 User는 프록시를 이용해서 가져온다.

이와 반대되는 개념으로는 eager-fetching(지연 로딩)이 있다.

그리고 Article과 User Entity를 생성한다. 아래 예시는 Article Entity이다.

package com.example.kotlinserver.entities

import java.time.LocalDateTime
import javax.persistence.Entity
import javax.persistence.GeneratedValue
import javax.persistence.Id
import javax.persistence.ManyToOne

import com.example.kotlinserver.extensions.toSlug

@Entity
class Article(
    var title: String,
    var headline: String,
    var content: String,
    @ManyToOne var autor: User,
    var addedAt: LocalDateTime = LocalDateTime.now(),
    @Id @GeneratedValue var id: Long? = null,
    var slug: String = title.toSlug()
)

1편에서 만들었던 Extension 중 하나인 toSlug를 사용했다.

여기서도 문제를 겪었다.. 처음에 계속 unresolved method라고 해서 수동 import를 해줬는데도 못 알아듣길래 코틀린 사이트의 원본 소스코드를 확인해봤다. 난 자바처럼 파일 이름과 동일한 클래스를 생성하고 그 안에 Extension들을 선언해줬는데 그게 아니라 그냥 바로 Extension 클래스를 파일 안에 선언해서 구현하는 거였다..!
자바랑 비슷하지만 많이 다른 코틀린..

Entity를 구할 수 있는 Jpa Repository를 생성한다. 아래 예시는 ArticleRepository이다.

package com.example.kotlinserver.repositories

import com.example.kotlinserver.entities.Article
import org.springframework.data.repository.CrudRepository

interface ArticleRepository : CrudRepository<Article, Long> {
    fun findByTitle(title: String): Article?
    fun findAllByOrderByAddedAtDesc() : Iterable<Article>
}

다음과 같이 Repository 테스트를 진행하면 값을 제대로 찾아서 반환하는 것을 확인할 수 있다.

package com.example.kotlinserver

import com.example.kotlinserver.entities.Article
import com.example.kotlinserver.entities.User
import com.example.kotlinserver.repositories.ArticleRepository
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest
import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager
import org.springframework.data.repository.findByIdOrNull

@DataJpaTest
class RepositoriesTests @Autowired constructor(
    val entityManager: TestEntityManager,
    val articleRepository: ArticleRepository
){

    @Test
    fun `When findByIdOrNull then return Article`() {
        // given
        val newUser = User("s2moon98", "jieun", "moon")
        entityManager.persist(newUser)

        var newArticle = Article("new article title", "new headline", "new content", newUser)
        entityManager.persist(newArticle)

        entityManager.flush()

        // when
        // !!의 의미 : null이 들어올 수 없는 경우
        val found = articleRepository.findByIdOrNull(newArticle.id!!)

        // then
        assertThat(found).isEqualTo(newArticle)
    }
}

테스트 성공!

Article Entity를 선언할 때 id를 nullable로 선언했기 때문에 인자로 받을 때 !! 연산자를 사용한다.
!! 연산자는 모든 객체를 non-Null 타입으로 변경하며 null값이 들어올 경우 예외를 발생시킨다. (Null Pointer Exception과 비슷하게 생각 가능)

깃허브에서 코드 확인하기 : https://github.com/s2moon98/first-kotlin-server

profile
백엔드 개발자입니다.

0개의 댓글