티스토리 뷰

Java

spring boot에 jOOQ 적용하기#2

LichKing 2019. 5. 14. 10:05

두번째 포스팅을 할지말지 확신이 안섰는데 어느정도 삽질을 통해 알게된점들이 있어서 두번째 포스팅을 한다.

spring boot에 적용하기라는 제목치고는 앞선 포스팅에서 spring boot 관련 얘기가 하나도 없어서 이에 관한 내용도 적으려한다.

일단 기본적인 구성은 앞 포스팅에서 다 진행됐다. 간략한 테스트를 진행해보자.

 

jooq API를 사용할때는 DSLContext 객체를 이용하게되는데 이 객체는 spring boot 자동구성에 의해 spring bean으로 등록된다. 편하게 주입받아서 사용하면된다. 우리가 설정해줘야할것은 datasource 관련 설정만 해주면된다.

 

spring:
  datasource:
    driver-class-name: org.sqlite.JDBC
    url: jdbc:sqlite::resource:qsvc.splite3
  jooq:
    sql-dialect: sqlite

 

spring boot test는 단위테스트 지원을 위해 몇가지 특화된 애노테이션들을 지원해주고있다. @DataJpaTest, @WebMvcTest 등이 그것들인데 jooq를 위한 @JooqTest 애노테이션도 지원해주고있다.

 

@JooqTest
class JooqTest {
    @Autowired
    lateinit var create: DSLContext

    @Test
    fun `SQL builder로 사용`() {
        val sql = create.select(asterisk())
                .from(TABLE1)
                .sql

        println(sql)
    }

    @Test
    fun `SQL executor로 사용1`() {
        val result = create.select(asterisk())
                .from(TABLE1)
                .fetch()

        println(result)
    }

    @Test
    fun `SQL executor로 사용2`() {
        val result: List<Table1Record> = create.fetch(TABLE1)

        println(result)
    }
}

 

언어가 코틀린인건 감안하고 보자. 이해하는데 어려운점은 없을것이다.

첫번째 테스트는 sql builder로 sql을 만들어내는 테스트다. 이런식으로 타입안정성을 보장받으며 sql을 생성하고 실제 호출은 jdbcTemplate과 같은 다른 라이브러리를 이용할 수 있다.

 

두번째와 세번째 테스트는 query 실행까지 jooq를 이용하는 테스트다. 똑같은 결과를 받는 테스트인데 호출한 메서드가 약간 다른 방식이다.

 

    @Test
    fun `SQL executor로 사용3`() {
        val result = create.fetchOne(TABLE1, TABLE1.ID.eq(438))

        println(result)
    }

 

where 절을 이용하는 sql을 실행하는 테스트다. fetchOne 이라는 메서드명에서 알 수 있듯이 이 메서드는 리스트가 아니라 1건의 결과만을 준다.

 

    @Test
    fun `join 테스트1`() {
        val result = create.fetchOne(TABLE1.innerJoin(TABLE2)
                .on(TABLE1.ID.eq(TABLE2.ID))
                , TABLE1.ID.eq(438))

        println(result)
    }

 

이번엔 inner join을 실행하는 테스트다. 대충 흐름을 보면 알겠지만 실제 SQL을 작성하는 것과 거의 유사하게 메서드를 작성하면된다. 더욱이 지금 이 테스트는 fetchOne안에 인자를 전달하는 형태라 약간 보기힘든데

 

    @Test
    fun `SQL executor로 사용1`() {
        val result = create.select(asterisk())
                .from(TABLE1)
                .fetch()

        println(result)
    }

 

이 형태로 사용하면 좀 더 SQL 스럽게 작성할 수 있다.

다만 이 방식을 쓰게되면 한가지 우려되는점이 있었는데 저 쿼리들의 실행결과가 jooq가 생성해준 클래스 타입으로 리턴된다는 점이다. 실제 비즈니스 코드에 jooq가 생성해준 클래스를 사용하는건 굉장히 부담스럽고 권장하지않는 방식이다. 그래서 내가 생각한 방법은 저 결과물들을 우리 코드안의 클래스타입으로 변환해주는 코드를 작성하는 것이다. 하지만...

 

    @Test
    fun `쿼리 결과 POJO로 변환`() {
        val pojos: List<Pojo> = create.fetch(TABLE1, TABLE1.ID.eq(1)).into(Pojo::class.java)

        println(pojos)
    }

    data class Pojo(private val id: Int,
                    private val name: String?)

 

이미 jooq에서는 타입을 변환해주는 api까지 제공하고있으니 이를 사용하면 굳이 변환 코드를 작성하지않아도된다. data class는 코틀린에서 지원하는 문법인데 자바로치면 보통의 java bean이라고 보면된다. 바로 POJO(plain old java object)인 것이다.

 

setter를 지원하지않는 불변 객체를 사용하고있다면 생성자에 @ConstructorProperties를 이용해주면 생성자를 통해 객체를 만들어준다.

 

@ConstructorProperties({"id", "name"})
class Pojo{
  private Integer id;
  private String name;
}

 

참고로 @ConstructorProperties는 jackson, lombok 관련 포스팅에서 언급한적이 있다.

 

이로써 앞선 포스팅에서 jooq 에 대해 전반적으로 살펴봤고, 이번 포스팅에선 spring boot test와 함께 간단한 단위테스트를 작성했다. 앞으로도 계속 jooq를 사용할 예정이므로 또 발견하는 것들이있으면 추가포스팅을 작성할 예정이다.

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함