Querydsl vs Criteria API vs QueryMethod vs JPQL 비교
이전 포스팅에서 Querydsl 을 설정하는 방법을 알아보았습니다.
Link : https://aljjabaegi.tistory.com/691
이번에는 JPA에서 활용되는 여러가지 방법들과 Querydsl을 비교해 보도록 하겠습니다.
샘플 쿼리에 있는 내용을 Query method,
샘플 쿼리
SELECT CD_ID
, CD_NM
, CD_SQNO
FROM M_OP_CD
WHERE GRP_CD_ID = #{grpCdId}
ORDER BY CD_SQNO ASC
1. Query Method
@Repository
public interface CodeRepository extends JpaRepository<M_OP_CD, M_OP_CD_KEY> {
List<M_OP_CD> findByKeyGrpCdIdOrderByCdSqnoAsc(String grpCdId);
}
JPA에서 가장 간단하게 데이터를 조회할 수 있는 방법입니다.
방식만 알면 쉽고 간편하게 사용이 가능하죠. 하지만 복잡한 쿼리의 경우 작성하기 어렵고, 모든 쿼리를 구현하는데는 무리가 있습니다. 간단한 CRUD 작업에만 용이합니다.
Link : https://aljjabaegi.tistory.com/678
2. JPQL ( Java Persistence Query Language) and nativeQuery
@Repository
public interface CodeRepository extends JpaRepository<M_OP_CD, M_OP_CD_KEY> {
@Query(value = "SELECT CD_ID" +
", CD_NM" +
", CD_SQNO" +
" FROM M_OP_CD" +
" WHERE GRP_CD_ID = :grpCdId" +
" ORDER BY CD_SQNO ASC"
)
List<M_OP_CD> findByKeyGrpCdIdOrderByCdSqnoAsc(@Param("grpCdId") String grpCdId);
}
JPQL, nativeQuery를 사용해서 queryMethod의 단점을 보완할 수 있습니다. 위와 같이 @Query 를 사용해 value에 쿼리를 String으로 연결해주시면 됩니다. nativeQuery의 경우 @Query 에 nativeQuery = true 옵션만 주시면 됩니다.
쿼리를 작성해주면 되지만, 보시는데로, String이기 때문에 수정 시 어려움이 있고, 컴파일 시점에 오류를 파악할 수 없습니다.
3. CriteriaBuilder
public interface CodeRepository {
List<M_OP_CD> findByKeyGrpCdIdOrderByCdSqnoAsc(String grpCdId);
}
@Repository
public class CodeRepositoryImpl implements CodeRepository {
private final EntityManager entityManager;
@Autowired
public CodeRepositoryImpl(EntityManager entityManager) {
this.entityManager = entityManager;
}
@Override
public List<M_OP_CD> findByKeyGrpCdIdOrderByCdSqnoAsc(String grpCdId) {
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<M_OP_CD> query = criteriaBuilder.createQuery(M_OP_CD.class);
Root<M_OP_CD> code = query.from(M_OP_CD.class);
CriteriaQuery<M_OP_CD> criteriaQuery = query.select(code);
Path<M_OP_CD_GRP> grpCd = code.get("key");
Predicate predicate = criteriaBuilder.equal(grpCd.get("grpCdId"), grpCdId);
criteriaQuery = criteriaQuery.where(predicate);
return entityManager.createQuery(criteriaQuery).getResultList();
}
일단 criteriaBuilder를 사용하면 컴파일 시점에 에러를 잡아주는 장점이 있습니다.
JPQL 처럼 String으로 쿼리를 작성하지 않아도 되고, 좀 더 Java 스럽게 구현을 할 수 있죠.
하지만 간단한 쿼리가 너무 복잡해 졌죠. 간단한 쿼리도 이정도인데, 복잡한 쿼리는...말 안해도 아시겠죠?
4. Querydsl
public interface CodeRepository {
List<M_OP_CD> findByKeyGrpCdIdOrderByCdSqnoAsc(String grpCdId);
}
@Repository
public class CodeRepositoryImpl implements CodeRepository {
private final JPAQueryFactory jpaQueryFactory;
@Autowired
public CodeRepositoryImpl(JPAQueryFactory jpaQueryFactory) {
this.jpaQueryFactory = jpaQueryFactory;
}
@Override
public List<M_OP_CD> findByKeyGrpCdIdOrderByCdSqnoAsc(String grpCdId) {
QM_OP_CD code = QM_OP_CD.m_OP_CD;
return jpaQueryFactory.selectFrom(code)
.where(code.key.grpCdId.eq(grpCdId))
.orderBy(code.cdSqno.asc()).fetch();
}
}
매우 간단하죠?
Criteria API의 단점은 버리고, 장점과 쿼리의 장점만을 조합한 것 같은 느낌입니다.
다양한 DB에서 사용할 수 있고, 쿼리만 작성할 줄 안다면 사용법도 금방 익숙해 질 수 있습니다.
쿼리와 비슷하기 때문에 가독성도 좋고 DB에서 지원하는 기능들을 거의 모두 지원하기 때문에 매우 파워풀 하죠.
써야되는 이유는 명확해졌습니다.
다음 포스팅에서는 Querydsl의 다양한 기능에 대해서 알아보겠습니다.