jpql문법

  • select m from Member as m where m.age > 18
    -> Member : 엔티티속성, 대소문자 구분
    java클래스는 대소문자를 구분하기 때문
    엔티티이름 사용, 테이블이름 아님
    엔티티 이름을 @Entity(name = "mm")으로 수정시 jpql에서도 mm으로 써야 한다.
    -> jpql 키워드 : select, from, where 대소문자 구분 안함

    집합과 정렬

    select m
    count(m) //회원 수
    sum(m.age) //나이 합
    avg(m.age) //평균 나이
    max(m.age) //최대 나이
    min(m.age) //최소 나이

from Member m

  • group by, having
  • order by

TypeQuery, Query 리턴되는 결과값 가져오기

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

TypeQuery query = em.createQuery("select m from member m", Member.class);

Query query = em.createQuery("select m.username,m.age from Member m");

package com.codingbox.jpql;

import java.util.List;



import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityManagerFactory;
import jakarta.persistence.EntityTransaction;
import jakarta.persistence.Persistence;
import jakarta.persistence.Query;
import jakarta.persistence.TypedQuery;

public class JpaMain {

	public static void main(String[] args) {
		EntityManagerFactory emf 
			= Persistence.createEntityManagerFactory("hello");
		EntityManager em = emf.createEntityManager();
		EntityTransaction tx = em.getTransaction();
		tx.begin();
		
		Member member = new Member();
		member.setUsername("member1");
		em.persist(member);
		
		//두번째 파라미터로 응답 클래스에 대한 type정보를 줄 수 있다.
		TypedQuery<Member> query = em.createQuery("select m from Member m",Member.class);
		
		//타입정보가 String.class로 반환타입이 명확할 때
		TypedQuery<String> query2 = em.createQuery("select m.username from Member m",String.class);
		
		//String, int : 이렇게 반환타입이 명확하지 않을 때
		Query query3 = em.createQuery("select m.username,m.age from Member m "); //이건 파라미터 하나로 받아오는 거
		
		TypedQuery<Member> query4 = em.createQuery("select m from Member m",Member.class);
		
		List<Member> resultList = query4.getResultList();
		for(Member m : resultList) {
			System.out.println("m = " + m );
		}
		
		TypedQuery<Member> query5 = em.createQuery("select m from Member where m.id", Member.class); //pk값으로 조회했으니까 한건만 나옴
		Member result = query5.getSingleResult();
		System.out.println("result : " +result);
		
		
		tx.commit();
		
		em.close();
		emf.close();
	}

}

예시코드를 가져와 봤다. select m from Member m이 쿼리문은 엔티티 전체를 말하지만
select m.username from Member m이 쿼리는 username만을 조회한다.
또한
Query query3 = em.createQuery("select m.username,m.age from Member m ");
TypedQuery query4 = em.createQuery("select m from Member m",Member.class);
이 두 코드를 분석하면 query를 통해 가져오면 반환타입이 명확하지 않기에 파라미터를 하나만 가져온다. 하지만 TypedQuery같은 경우 반환타입이 명확하여 파라미터를 2개 취한다.

결과 조회

  • query.getResultList() : 결과가 하나 이상일 때, 리스트 반환
    -> 결과가 없으면 빈 리스트 반환
    -> 빈 collection이 반환되기 때문에 NullPointException에 대한 걱정은 안해도 된다.

  • query.getSingleResult() : 결과가 정확히 하나(조심), 단일 객체 반환
    -> 결과가 없으면 : NoResultException
    -> 결과가 둘 이상이면 : NonUniqueResultException

파라미터 바인딩

  • 이름 기준
    select m from Member m where m.username = :username
    query.setParameter("username",usernameParam); //파라미터 바인딩
    //파라미터 바인딩
    		TypedQuery<Member> query = em.createQuery("select m from Member m where m.username = :username",Member.class);
    		query.setParameter("username", "member1");
    		Member result = query.getSingleResult();
    		System.out.println("result : " + result.getUsername());
    		System.out.println("----------------------------------------");
    		
    		//파라미터 바인딩 - 메시지 체인방법
    		Member result2 = em.createQuery("select m from Member m where m.username = :username",Member.class)
    							.setParameter("username", "member1")
    							.getSingleResult();
    
    
    
  • 위치 기준 - 쓰지 말것
    select m from Member m where m.username = ?1
    	query.setParameter(1,usernameParam);

프로젝션

  • select 절에 조회할 대상을 지정하는 것
  • 프로젝션 대상 : 엔티티, 임베디드 타입, 스칼라 타입(숫자, 문자 등 기본 데이터 삽입)
    -select m from member m -> Member 엔티티 조회
    -select m.team from Member m -> Member와 관련된 team을 가지고 온다
  • select m.address from Member m -> 임베디드 타입을 가지고 있다.
    -select m.username, m.age from Member m -> 스칼라 타입 프로젝트

페이징 api

  • jpa는 페이지를 다음 두 API로 추상화
  • setFirstResult(int startPoint) : 조회 시작 위치(0부터 시작)
  • setMaxResults(int maxResult) : 조회할 데이터 수
    -> 몇 번째 부터 몇 건을 가지고 올래?
package com.codingbox.jpql;

import java.util.List;



import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityManagerFactory;
import jakarta.persistence.EntityTransaction;
import jakarta.persistence.Persistence;
import jakarta.persistence.Query;
import jakarta.persistence.TypedQuery;

public class JpaMain5 {

	public static void main(String[] args) {
		EntityManagerFactory emf 
			= Persistence.createEntityManagerFactory("hello");
		EntityManager em = emf.createEntityManager();
		EntityTransaction tx = em.getTransaction();
		tx.begin();
		
	
//		Member member = new Member();
//		member.setUsername("memeber1");
//		member.setAge(10);
//		em.persist(member);
		
		em.flush();
		em.clear(); //이 두 코드를 지난 후 준영속 상태
		for(int i = 1; i <= 100; i++) {
			Member member = new Member();
			member.setUsername("member" +i);
			member.setAge(i);
			em.persist(member);
			
		}
		
		//페이징 처리
		String jpql = "select m from Member m order by m.age desc";
		List<Member> resultList= em.createQuery(jpql,Member.class)
									.setFirstResult(10)
									.setMaxResults(20)
									.getResultList();
		
		System.out.println("result.size = " + resultList.size());
		for(Member m : resultList) {
			System.out.println("m : " + m.toString());
		}
		
		tx.commit();
		em.close();
		emf.close();
	}

}

원래대로라면 100개를 가져와야 하는데 20개 밖에 가져오지 않는다. setMaxResults(20)을 통해 최대 20개의 정보를 가져온다.

조인

  • 문법이 객체 스타일로 나간다.

  • 내부조인
    -> select m from Member m(inner) join m.team t

  • 외부조인
    -> select m from Member m left (outer) join m.team t

서브쿼리

  • From절의 서브쿼리는 현재 jpql에서는 불가능, 조인으로 풀 수 있으면 풀어서 해결
profile
초보 개발자 이야기

0개의 댓글

관련 채용 정보