QL 기본 문법 - 1

16682 단어 JPAJPA

JPQL

SQL - 데이터베이스 테이블을 대상으로 쿼리
JPQL - 엔티티 객체를 대상으로 쿼리
JPQL로 작성해도 결국 SQL로 변환되어 DB에 적용

String jpql = "select m From Member m where m.name like '%hello%'";

List<Member> result = em.createQuery(jpql, Member.class)
                        .getResultList();

for (Member member : result) {
     System.out.println("member = " + member);
 }

SQL과 매우 유사한 문법
하지만 이와 같은 코드 작성은 동적 쿼리를 생성하는 데에 어려움이 있음
=> QueryDSL 등장(추후 설명)

문법

select m from Member as m where m.age > 18

  • 엔티티는 대소문자 구분됨
  • JPQL 키워드는 대소문자 구분 X
  • 테이블 명이 아닌 엔티티 이름 사용
  • 별칭은 필수(m), as는 생략 가능

TypeQuery, Query

  • TypeQuery : 반환 타입이 명확할 때 사용
  • Query : 반환 타입이 명확하지 않을 때 사용
TypedQuery<Member> query1 = 
em.createQuery("select m from Member m", Member.class);

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

Query query3 = 
em.createQuery("select m.username, m.age from Member m"); 
// m.username과 m.age => 어떤 타입 반환해야 할지 애매함   

이들을 getResultList(), getSingleList()를 통해 조회할 수 있음

query.getResultList() : 결과가 하나 이상일 때, 리스트 반환
(결과가 없으면 빈 리스트 반환)
query.getSingleList() : 결과가 정확히 하나일 때 단일 객체 반환
(결과가 없거나 둘 이상이면 예외 발생)

아래와 같이 조회하면 됨

 List<Member> resultList = query1.getResultList();

 for (Member member1 : resultList) {
 	System.out.println("member1 = " + member1);
 }

파라미터 바인딩

이름 기준

TypedQuery<Member> query = 
em.createQuery("select m from Member m where m.username = :username", Member.class);
query.setParameter("username", "member1");

Member singleResult = query.getSingleResult();
System.out.println("singleResult = " + singleResult);

또는 아래와 같이 표현함

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

위치를 기준으로 표현할 수도 있지만,
이는 장애를 발생시킬 가능성이 높으므로 사용 권장하지 않음
(중간에 엔티티 삽입되면 순서가 전부 바뀌는 경우 등의 이유)

프로젝션

SELECT 절에 조회할 대상을 지정하는 것

예시
1. SELECT m From Member m; : 엔티티 프로젝션
2. SELECT m.team From Member m; : 엔티티 프로젝션
3. SELECT m.address From Member m; : 임베디드 타입 프로젝션

여러 값 조회
ex) m.username, m.age를 조회 하려고 하면?
=> Object 타입 사용

List resultList = em.createQuery("select m.username, m.age from Member m")
                    .getResultList();
Object o = resultList.get(0);
Object[] result = (Object[]) o;

또는

List<Object[]> resultList = 
em.createQuery("select m.username, m.age from Member m")
  .getResultList();
  
Object[] result = resultList.get(0);

따로 객체를 만드는 방법도 있다.

List<MemberDTO> result = em.createQuery("select new jpql.MemberDTO(m.username, m.age) from Member m, MemberDTO.class)
 			   .getResultList();
MemberDTO memberDTO = result.get(0);

MemberDTO에 생성자 필수

페이징

  • setFirstResult(int startPosition) : 조회 시작 위치(0부터 시작)
  • setMaxResults(int maxResult) : 조회할 데이터 수

예시

//페이징  쿼리
  String jpql = "select m from Member m order by m.name desc"; 
  
  List<Member> resultList = em.createQuery(jpql, Member.class)
        .setFirstResult(10)         
        .setMaxResults(20)         
        .getResultList();
        

서브쿼리

EXISTS, ALL, ANY, SOME, NOT IN 등 지원 가능

JPQL은 WHERE, HAVING, SELECT 절에서 서브쿼리 사용이 가능하고
From에서의 서브쿼리는 지원하지 않는다.

ex) select ~~ from (select ~~) as ~~ 실행 X

타입 체크 - select i from Item I where type(i) = Book

조건식 - CASE도 작성 가능하다.

String query =
         "select " +
	        "case when m.age <= 10 then '학생요금' " +
	        "       when m.age >= 60 then '경로요금' " +
	        "       else '일반요금' " +
	        " end " +
           "from Member m";
  • coalesce : 하나씩 조회해서 null이 아니면 반환
    select coalesce (m.username,'이름 없는 회원') from Member m

  • NULLIF : 두 값이 같으면 null 반환, 다르면 첫 번째 값 반환
    select NULLIF(m.username, '관리자') from Member m

    CONCAT, SUBSTRING, TRIM등의 함수 역시 JPQL에서도 사용 가능

좋은 웹페이지 즐겨찾기