JPA - JPAQuery와 Q클래스

2019. 2. 11. 23:43Web/JPA

JPA - JPAQuery와 Q클래스


긴 포스팅은 아니지만 예제로 소스를 짜는 도중에 몰랐던 내용을 알게되어서 작성한다. QueryDSL로 예제중 나온 상황이다.



1
2
3
4
5
6
7
8
9
10
public List<MyEntity> findMyDumbEntities(long id) {    
      QMyEntity qMyEntity = QMyEntity.myEntity;
      JPAQuery jpaQuery = new JPAQuery(entityManager);
      MyEntity myFirstEntity = jpaQuery.from(qMyEntity)
                                        .where(qMyEntity.id.eq(id)).uniqueResult(qMyEntity);
      MyEntity mySecondEntity = jpaQuery.from(qMyEntity)
                                        .where(qMyEntity.id.eq(id+1)).uniqueResult(qMyEntity);
 
      return Arrays.asList(myFirstEntity, mySecondEntity);    
}
cs


언뜻 보기에는 크게 문제가 없는 듯 싶다. 하지만 이 소스를 실행하면 이러한 예외가 발생한다.



java.lang.IllegalStateException: qMyEntity is already used


즉, 같은 JPAQuery 객체로 같은 Q타입클래스를 사용할 수없는 것이다. 사실 내부를 까보지는 않아서 원인파악은 해보아야겠지만 일단 결론은 그렇다. 그렇기 때문에 소스가 이런식으로 변경되어야한다.


1
2
3
4
5
6
7
8
9
public List<MyEntity> findMyDumbEntities(long id) {        
          QMyEntity qMyEntity = QMyEntity.myEntity;
          MyEntity myFirstEntity = new JPAQuery(entityManager).from(qMyEntity)
                                    .where(qMyEntity.id.eq(id)).uniqueResult(qMyEntity);
          MyEntity mySecondEntity = new JPAQuery(entityManager).from(qMyEntity)
                                    .where(qMyEntity.id.eq(id+1)).uniqueResult(qMyEntity);
 
          return Arrays.asList(myFirstEntity, mySecondEntity);        
}
cs


이런식으로 JPAQuery 객체를 만드는 메소드를 하나 정의하는 것이 좋을 것같다.


1
2
3
4
5
6
7
8
9
10
11
12
13
 
protected JPQLQuery jpaQuery() {
    return new JPAQuery(entityManager);
}
 
@Override
public List<Article> findAll() {
      return jpaQuery().from(article).fetchAll().list(article);
}
 
public Article findById(@Nonnull final long id) {
      return jpaQuery().from(article).where(article.id.eq(id)).uniqueResult(article);
}
cs

언젠가는 이런 상황이 닥칠수도 있을 것같아서 포스팅한다..