Develop/spring-data

[JPA] JPA를 적용하며... mysql 함수 2번 호출되는 문제

에디개발자 2020. 12. 6. 07:00
반응형

왜 querydsl로 조회할때 mysql 함수가 두 번 발생하는 문제가 나타났습니다.

먼저 Spring Data JPA를 사용하면서 왜 mysql 함수를 썼어야 했는지부터 설명드리겠습니다.

진행중인 프로젝트는 mybatis를 사용했었습니다. 그리고 새로운 버전으로 업그레이드하면서 JPA를 도입했고 기존 mapper 쿼리를 걷어내면서 작업을 진행하고 있습니다. 그래서 mybatis를 걷어내기 전까지는 mysql를 함수를 사용하기로 하였습니다. ( 관리포인트를 2개로 나누는 것은 좋지 않다고 판단 )

 

증상

querydsl로 아래 소스처럼 mysql function을 이용하여 조회하는 로직이 있습니다. 그런데 function이 두번 호출되고 있습니다.

public StoreVo findByName(String name) {
    return jpaQueryFactory
            .select(Projections.fields(StoreVo.class,
                    store.id
                    , Expressions.stringTemplate("createPrefix({0})", store.name).as("name")
                    , store.address
                    ))
            .from(store)
            .where(store.name.eq(name))
            .limit(1L)
            .fetchOne();
}

로그

select
    store0_.id as col_0_0_,
    createPrefix(CreatePrefix(account_number)) as col_1_0_,
    store0_.address as col_2_0_ 
from
    store store0_ 
where
    CreatePrefix(account_number)='스토어6' limit 1

 

 

원인

분명히 테스트 완료한 코드인데 갑자기 왜 이러지..? 하면서 예제 코드와 비교하면서 원인을 찾았습니다. 삽질..

직장 동료의 도움으로 원인을 찾았습니다. Entity에 @ColumnTransformer 를 사용하고 있었습니다. 이러니 당연히 Querydsl에서 function 호출하고 Entity에서 또 호출하고 있었습니다.

@Getter
@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Store {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @ColumnTransformer(read = "CreatePrefix(account_number)", write = "CreatePrefix(?)")
    private String name;
    private String address;

    @Builder
    public Store(Long id, String name, String address) {
        this.id = id;
        this.name = name;
        this.address = address;
    }
}

 

해결

Querydsl에서 function을 제거하여 문제가 해결되었습니다.

@Getter
@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Store {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
//    @ColumnTransformer(read = "CreatePrefix(account_number)", write = "CreatePrefix(?)")
    private String name;
    private String address;

    @Builder
    public Store(Long id, String name, String address) {
        this.id = id;
        this.name = name;
        this.address = address;
    }
}

로그

select
    store0_.id as col_0_0_,
    createPrefix(store0_.name) as col_1_0_,
    store0_.address as col_2_0_ 
from
    store store0_ 
where
    store0_.name='스토어6' limit 1

 

 

 

p.s 집단 지성은 강력하다! 소스는 거짓말하지 않는다! 내가 거짓말할 뿐...

반응형