주요글: 도커 시작하기
반응형

JPA를 이용해서 구현하는 프로젝트에서 두 개의 프로퍼티를 묶어서 식별자로 사용해야 하는 경우가 생겼다. 그래서, @EmbeddedId를 이용해서 ID 필드를 지정하였다. 이 프로젝트는 Spring Data JPA를 이용해서 Repository를 자동생성하고 있는데, @EmbeddedId 부분에서 문제가 발생했다. 아래 코드는 문제를 발생시킨 리포지토리의 인터페이스이다.


public interface FollowRepository extends Repository<Follow, FollowId> {


    Page<Follow> findAll(Specification<Follow> spec, Pageable pageable);

...

}


Follow의 식별자의 타입은 FollowId 클래스이고, FollowId 클래스는 두 개의 프로퍼티를 갖고 있다. 그런데, 위 코드에서 findAll()을 실행하는 순간에 다음과 같은 쿼리가 실행되면서 문제가 발생했다.


select count((follow0_.FOLLOWING_ID, follow0_.USER_ID)) as col_0_0_ 

from FOLLOW follow0_ 

where ....


DBMS로 오라클을 사용하고 있는데, 위 count() 부분에서 쿼리 오류가 발생한 것이다. 처음엔 Spring Data JPA 문제일까 해서 커스텀 구현을 넣어 보았다.


public class FollowRepositoryImpl implements FollowRepositoryCustom {


    @PersistenceContext

    private EntityManager entityManager;


    @Override

    public Page<Follow> findAll(Specification<Follow> spec, Pageable pageable) {

        List<Follow> result = getResultList(spec, pageable);

        long total = count(spec);

        return new PageImpl<Follow>(result, pageable, total);

    }


    private List<Follow> getResultList(Specification<Follow> spec,

            Pageable pageable) {

        ...

        return query.getResultList();

    }


    private long count(Specification<Follow> spec) {

        CriteriaBuilder cb = entityManager.getCriteriaBuilder();

        CriteriaQuery<Long> c = cb.createQuery(Long.class);

        Root<Follow> root = c.from(Follow.class);

        c.select(cb.count(root));

        Predicate predicate = spec.toPredicate(root, c, cb);

        c.where(predicate);


        TypedQuery<Long> query = entityManager.createQuery(c);

        return query.getSingleResult();

    }


}


하지만, 결과는 동일했다. JPA API를 직접 사용해도 변화가 없는 걸 봐서는 Spring Data JPA의 문제는 아니였다. Spring Data JPA 1.1 버전을 사용하고 있었는데, 이 버전은 하이버네이트 3.6.9를 기준으로 하고 있어서 해당 버전의 하이버네이트를 사용했었다.


하이버네이트의 버전 문제가 아닐까해서 범위를 좀 더 좁혀서 구글링을 해 봤더니 하이버네이트에서 이런 문제가 발생하고 있는 듯 했다. (관련 문의가 포럼에 있었다.) 좀 더 파 볼까 하다가, 하이버네이트 버전을 올려보기로 결심했다. 하이버네이트 버전을 3.6.9에서 4.1.4로 올렸다.


결과는? 야호! 테스트케이스의 녹색바! 에러가 없어졌다. 처음부터 하이버네이트 버전 업부터 할 걸, 괜히 코드 작성했다. 오픈소스에서 뭔가 이상한 문제가 있으면 먼저 버전을 올려보라는 걸 다시 한 번 확인했다.


+ Recent posts