JPQL 기본 문법

Ango·2023년 7월 8일

SPRING

목록 보기
11/13

JPQL 이란

JPQL은 특정 조건의 필요한 데이터만 DB에서 조회하려면 결국 JPA 만으로도 한계가 있음. 때문에 검색 조건이 포함된 SQL을 직접 작성해야 할 때가 있다. 이때 JPA는 SQL을 추상화한 JPQL이라는 객체지향 쿼리언어를 제공한다.

  • SQL문법과 유사하여 대부분의 무넙을 지원한다.
  • 테이블을 대상으로 쿼리문을 날리는 SQL과 다르게 엔티티 객체를 대상으로 쿼리문을 날린다.
  • EX) select m From Member as m where m.age > 18
  • 엔티티의 이름을 사용해야한다. (테이블 이름 x)
  • 별칭은 필수이다.

TypeQuery, Query

TypedQuery<Member> query = em.createQuery("select m from Member m ", Member.class); // 조회하려는 타입이 Member로 명확

Query query1 = em.createQuery("select m.age, m.username from Member m");// int 타입,String 타입 등 불명확 
  • TypeQuery: 반환 타입이 명확할 때 사용
  • Query: 반환 타입이 명확하지 않을 때 사용

단건조회

TypedQuery<Member> query = em.createQuery
							("select m from Member m ", Member.class);
Member member1 = query.getSingleResult();

결과가 없거나 , 여러개면 에러가 뜬다.
무조건 1개가 조회돼야함

• 결과가 없으면: javax.persistence.NoResultException
• 둘 이상이면: javax.persistence.NonUniqueResultException

다건조회

TypedQuery<Member> query = em.createQuery
							("select m from Member m ", Member.class);
List<Member> memberList = query.getResultList();

집계함수
Count,SUM,AVG,MAX,MIN 과같은 SQL문에서 지원하는 집계함수도 모두 사용 가능한다.

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

파라미터 바인딩

 Query query1 = em.createQuery(select m.age, m.username from Member " +
                            "m where m.age= :userage", Member.class)
                           .setParameter("userage", 20);

프로젝션

- SELECT m FROM Member m -> 엔티티 프로젝션
- SELECT m.team FROM Member m -> 엔티티 프로젝션
- SELECT m.address FROM Member m -> 임베디드 타입 프로젝션
- SELECT m.username, m.age FROM Member m -> 스칼라 타입 프로젝션 (숫자, 문자 등 기본 데이터 타입)

select m.username, m.age from Member m
즉 int타입인 age와 String 타입인 username을 같이 조회한다고 할때 조회하는 방법을 소개해보겠다.

1) 여러 값 조회

  • Query 타입으로 조회
List resultList = em.createQuery("select m.username,m.age from Member m ").getResultList();

Object o = resultList.get(0);
Object[] result = (Object[]) o;
System.out.println("username = " + result[0]);
System.out.println("age = " +result[1]);
  • Object[] 타입으로 조회
List<Object[]> result = em.createQuery("select m.name, m.age from Member m ").getResultList();

for (Object[] objects : result) {
    out.println("user name = " + objects[0]);
    out.println("user age = " + objects[1]);
}
  • new 명령어로 조회
@AllArgsConstructor
@ToString
public class MemberDto {
	private String name;
	private int age;
}


TypedQuery<MemberDto> query =
    em.createQuery("select new jpql.MemberDto(m.name, m.age) from Member m ", MemberDto.class);
List<MemberDto> resultList = query.getResultList();

for (MemberDto memberDto : resultList) {
    out.println("memberDto = " + memberDto);
}

• 단순 값을 DTO로 바로 조회
SELECT new jpabook.jpql.UserDTO(m.username, m.age) FROM Member m
• 패키지 명을 포함한 전체 클래스 명 입력
• 순서와 타입이 일치하는 생성자 필요

페이징

 //페이징 쿼리
 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();
  • setFirstResult(int startPosition) : 조회 시작 위치 (0부터 시작)
  • setMaxResults(int maxResult) : 조회할 데이터 수

조인

SELECT m, t FROM Member m LEFT JOIN m.team t 

1) 조인 대상 필터링

SELECT m, t FROM Member m LEFT JOIN m.team t on t.name = 'A'

2) 연관관계 없는 엔티티 외부조인

SELECT m, t FROM Member m LEFT JOIN Team t on m.username = t.name
profile
웹 벡엔드 개발자가 되어보자!

0개의 댓글