저작권 안내: 저작권자표시 Yes 상업적이용 No 컨텐츠변경 No

스프링5 입문

JSP 2.3

JPA 입문

DDD Start

인프런 객체 지향 입문 강의

'@EmbeddedId'에 해당되는 글 1건

  1. 2012.07.12 Hibernate 3.6에서 JPA의 @EmbeddedId 사용시 오라클 count 관련 오류 (3)

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로 올렸다.


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


Posted by 최범균 madvirus

댓글을 달아 주세요

  1. 권남 2012.07.12 17:37 신고  댓글주소  수정/삭제  댓글쓰기

    @IdClass를 사용할때도 마찬가지 현상이 발생합니다.
    @IdClass/MySQL

  2. PKH갈휘 2012.07.16 22:22 신고  댓글주소  수정/삭제  댓글쓰기

    버전업후에 말끔해졌네요, 감사합니다.