본문 바로가기
자바/JPA

[JPA/Java] 객체지향 쿼리 언어 종류

by drCode 2023. 4. 27.
728x90
반응형

JPA는 다양한 쿼리 방법을 지원하고 있다.

 

JPQL, JPA Criteria, QueryDSL, 네이티브 SQL 등등

 

이 중에서 JPQLQueryDSL을 현업에서 많이 사용한다고 한다.

 

이 외에도 JDBC API를 직접 사용하기도 하고, MyBatis와 SpringJdbcTemplate을 함께 사용하기도 한다.

 

 

먼저, JPQL에 대해서 알아보자.

 

※ JPQL

JPQL은 가장 단순한 조회 방법이다. EntityManager.find()를 이용하거나, 객체 그래프 탐색(a.getB().getC()) 와 같은 형식으로 찾기도 한다.

JPA를 사용하면 엔티티 객체 중심으로 개발이 가능한데,

문제는 검색쿼리를 사용할 때이다.

여기서 보통 쿼리로 조건을 줄때, WHERE 절을 사용하는데, 조건을 주고싶을 땐 어떻게 해야할까??

 

검색을 할 때도 테이블이 아닌 엔티티 객체를 대상으로 검색하는데, 모든 DB 데이터를 객체로 변환해서 검색하는 것은 불가능하다.

그래서 애플리케이션이 필요한 데이터만 DB에서 불러오려면 결국 검색 조건이 포함된 SQL이 필요하다.

 

JPA는 SQL을 추상화한 JPQL이라는 객체 지향 쿼리 언어를 제공하고 있다

SQL과 문법이 유사하고, SELECT, FROM, WHERE, GROUP BY, HAVING, JOIN을 지원한다.

JPQL은 엔티티 객체를 대상으로 쿼리를 하는 것이다.

SQL은 데이터베이스 테이블을 대상으로 쿼리하는 것이다.

 

JPQL 작성은 아래와 같이 하면 된다.

//검색
 String jpql = "select m From Member m where m.name like ‘%hello%'"; 
 List<Member> result = em.createQuery(jpql, Member.class)
                         .getResultList();

테이블이 아닌 객체를 대상으로 검색하는 객체 지향 쿼리이기에,

SQL을 추상화해서 특정 데이터베이스 SQL에 의존하지 않는다.

JPQL을 한마디로 정의하면 객체 지향 SQL이다.

 

아래는 JPQL을 작성하고 실행한 결과이다.

String sql = "select m from Member m where m.userName like '%kim%'";

List<Member> resultList = em.createQuery(
        sql,
        Member.class
).getResultList();

JPQL 실행 이미지

 

※ Criteria 소개

Criteria는 JPA가 제공하는 쿼리 방법 중 하나이다.

문자가 아닌 자바코드로 JPQL을 작성할 수 있고, JPQL의 빌더 역할을 한다.

JPA 공식 문서에 등록된 기술이긴 하나, 너무 복잡하고 실용성이 없다.

Criteria 대신에 QueryDSL을 사용하기를 권장하는 추세이다.

 

Criteria 사용은 아래와 같다.

//Criteria 사용 준비
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Member> query = cb.createQuery(Member.class);

Root<Member> m = query.from(Member.class);
CriteriaQuery<Member> cq =
		query.select(m).where(cb.equal(m.get("userName"), "kim"));
CriteriaQuery<Member> cq = query.select(m);

 

동적 쿼리로 작성할 수도 있다.

//Criteria 사용 준비
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Member> query = cb.createQuery(Member.class);

Root<Member> m = query.from(Member.class);
CriteriaQuery<Member> cq = query.select(m);

// CriteriaQuery 동적 쿼리
String userName = "adsasd";
if(userName != null) {
    cq.where(cb.equal(m.get("userName"), "kim"));
}

 

위와 같이 조건을 줘서 쿼리를 작성할 수도 있다.

 

 

※ QueryDSL  소개

QueryDSL  역시 JPA가 제공하는 쿼리 기능이다.

문자가 아닌 자바코드로 JPQL을 작성할 수 있다.

JPQL 빌더 역할을 하며, 컴파일 시점에 문법 오류를 찾을 수 있다.

동적쿼리 작성이 편리하며, 단순하고 쉬우므로, 실무 사용을 권장하는 추세이다.

 

QueryDSL 사용은 아래와 같다.

 

//JPQL 
JPAFactoryQuery query = new JPAQueryFactory(em);
QMember m = QMember.member; 
List<Member> list = query.selectFrom(m)
                         .where(m.userName.like("kim")
                         .orderBy(m.userName.desc())
                         .fetch();

여기서 사용되는 QMember는 코드를 Generate하는 하나의 기능인데, 환경을 구성해야 사용할 수 있다.

 

 

※ Native SQL 소개

네이티브 SQL은 JPA가 제공하는 SQL을 직접 사용하는 기능이다.

JPQL로 해결할 수 없는 특정 데이터베이스에 의존적인 기능을 사용할 때 Native SQL을 사용한다.

예) 오라클 CONNECT BY, 특정 DB만 사용하는 SQL 힌트 등

 

Native SQL 코드는 아래와 같다.

String sql = "SELECT ID, AGE, TEAM_ID, NAME FROM MEMBER WHERE NAME = 'kim'"; 
List<Member> resultList = em.createNativeQuery(sql, Member.class)
                            .getResultList();

 

※ JDBC 직접사용, SpringJdbcTemplate 등

JPA를 사용하면서 JDBC 커넥션을 직접 사용하거나, SpringJdbcTemplate, MyBatis  등을 함께 사용이 가능하다.

단, 영속성 컨텍스트를 적절한 시점에 강제로 flush() 를 해줘야할 필요가 있다.

예) JPA를 우회해서  SQL을 실행하기 직전에 영속성 컨텍스트를 수동으로 flush() 해준다.

 

728x90
반응형

댓글