Web/JPA

EP11. JPQL소개, 기본문법

원래의 조회방법

EntityManager.find()

a.getB().getC()

 

그런데 나이가 18살 이상인 회원을 모두 검색하고 싶을 때 어떻게 조회할까?

-> SQL을 날려야 한다.

 

엔티티 중심으로 개발하기 위해 JPQL이 등장한다.

  • JPQL : 엔티티 객체를 대상으로 쿼리
  • SQL : DB테이블 대상으로 쿼리

 

JPQL 예시코드

List<Member> result = em.createQuery(
                    "select m From Member m where m.username like '%kim%'",
                    Member.class
            ).getResultList();

변환된 SQL

 

 

Criteria

java 코드로 jpql을 짤 수 있게 해준다. (jpa 표준스펙)

유지보수가 어려워서 실무에서는 사용하지 않는다.

 

 

QueryDSL

java 코드로 jpql을 짤 수 있게 해준다. (오픈소스 라이브러리)

그래서 동적쿼리 작성이 편리하다.

SQL과 비슷하게 생겨서 유지보수도 편리하다.

 

 

Native Query

실제 해당 데이터베이스 종속적인 쿼리를 짜야할 때

생쿼리 짜야할때 사용한다.

em.createNativeQuery("SELECT MEMBER_ID, city, street, zipcode, USERNAME from MEMBER ")
          .getResultList();

 

JDBC, SpringjdbcTemplate, mybatis

생 SQL 짜야할때 사용하는데, JPA와 관련없는 기술들이기 때문에 적절한 구간에서 영속성 컨텍스트를 flush 해주는 것이 필요하다.

 

 

 

 

JPQL (Java Persistence Query Language)

  • 엔티티 객체를 대상으로 쿼리한다. (테이블 대상이 아니다)
  • SQL을 추상화 했기 때문에 특정 DB에 의존하지 않는다.
  • 결국 SQL로 변환된다.

문법

  • select m from Member as m where m.age > 18
  • 테이블 이름이 아니라 엔티티로 씀 (Member)
  • 엔티티(Member), 속성(age) 은 대소문자 구분 O
  • JPQL키워드(select, FROM, Where) 은 대소문자 구분 X
  • 별칭 지정은 필수로 해야한다. (m) (as는 안써도됨)

 

집합과 정렬

select
	COUNT(m), //회원수
	SUM(m.age), //나이 합
	AVG(m.age), //평균 나이
	MAX(m.age), //최대 나이
	MIN(m.age) //최소 나이
from Member m

GROUB BY, HAVING, ORDER BY 사용가능

 

 

 

 

TypedQuery, Query

TypedQuery : 반환 타입이 명확할 때 사용

Query : 반환 타입이 명확하지 않을 때 사용

TypedQuery<Member> query1 = em.createQuery("select m from Member m", Member.class);
Query query2 = em.createQuery("select m.username, m.age from Member m");

query1 은 타입이 명확하므로 (Member) TypedQuery 사용

query2 는 m.username, m.age 가 타입이 달라서 명확하지 않으므로 Query 사용

 

 

결과 조회 API

query.getResultList()

결과가 하나 이상일 때 사용

결과가 없으면 빈 리스트 반환

 

query.getSingleResult()

결과가 단 한개일때만 사용

결과가 없으면 : NoResultException 오류

결과가 2개이상 : NonUniqueResultException 오류

 

 

파라미터 바인딩

코드

Member result = em.createQuery("select m from Member m where m.username = :username", Member.class)
        .setParameter("username", "member1")
        .getSingleResult();
System.out.println("result.getUsername() = " + result.getUsername());

쿼리