JPQL 이란
JPQL은 특정 조건의 필요한 데이터만 DB에서 조회하려면 결국 JPA 만으로도 한계가 있음. 때문에 검색 조건이 포함된 SQL을 직접 작성해야 할 때가 있다. 이때 JPA는 SQL을 추상화한 JPQL이라는 객체지향 쿼리언어를 제공한다.
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 타입 등 불명확
단건조회
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) 여러 값 조회
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]);
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]);
}
@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();
조인
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