반응형
본 내용은 온라인 강의 사이트 인프런의 김영한 님의 강의 내용이 포함되어 있습니다.
'자바 ORM 표준 JPA 프로그래밍 - 기본편'
타입 표현
JPQL에서 사용하는 타입은 다음과 같이 표시할 수 있으며, 대소문자는 구분하지 않는다.
문자
- 작은 따옴표(’) 사이에 표현
- 작은 따옴표(’)는 두 번 연속 사용하여 표현
- ex) ‘HELLO’, ‘She’’s’
숫자
- L(Long 타입), D(Double 타입), F(Float 타입)
- ex) 10L, 10D, 10F, 10
날짜
- DATE {d ‘yyyy-mm-dd’}, TIME {t ‘hh-mm-ss’}, DATETIME(ts ‘yyyy-mm-dd hh:mm:ss.f’}
- ex) {d ‘2022-12-05’}, {t ‘10-30-59’}, {ts ‘2022-12-05 10:30:59’}
- m.createDate = {d ‘2022-12-05’}
Boolean
- TRUE, FALSE
Enum
- 패키지명을 포함한 전체 이름을 사용해야 한다.
- ex) jpabook.MemberType.Admin
엔티티 타입
- 엔티티 타입을 표현, 주로 상속과 관련하여 사용한다.
- TYPE(m) = Member
Item 엔티티와 상속관계인 Book이 있다고 가정한 경우, 엔티티 타입이 Book인 Item 조회
em.createQuery("select i from Item i where type(i) = Book", Item.class);
타입 표현 간단 예시
Enum 타입이 ADMIN인 멤버에 대한 쿼리
- Enum 타입은 패키지명을 포함한 전체 이름을 사용해야 한다.
String query = "select m.username, 'HELLO', TRUE, false from Member m where m.type = jpql.MemberType.ADMIN";
List<Object[]> result = em.createQuery(query).getResultList();
for (Object[] objects : result) {
System.out.println("objects[0] = " + objects[0]); // m.username
System.out.println("objects[1] = " + objects[1]); // HELLO
System.out.println("objects[2] = " + objects[2]); // TRUE
System.out.println("objects[3] = " + objects[3]); // FALSE
}
// 출력
objects[0] = member1
objects[1] = HELLO
objects[2] = true
objects[3] = false
Enum 타입의 경우 파라미터 바인딩을 통해 조회할 수도 있다.
String query = "select m.username, 'HELLO', TRUE, false from Member m where m.type = :userType";
List<Object[]> result = em.createQuery(query)
.setParameter("userType", MemberType.ADMIN) // 파라미터 바인딩
.getResultList();
for (Object[] objects : result) {
System.out.println("objects[0] = " + objects[0]);
System.out.println("objects[1] = " + objects[1]);
System.out.println("objects[2] = " + objects[2]);
System.out.println("objects[3] = " + objects[3]);
}
기타식
JPQL은 SQL과 문법이 같은 식을 지원한다.
서브쿼리
- [NOT] EXISTS (subquert) : 서브 쿼리가 존재하면 참. NOT은 반대
- [NOT] IN (subquery) : 서브 쿼리의 결과 중 하나라도 같은 것이 있으면 참
- {ALL | ANY | SOME} (subquery) : 비교 연산자와 같이 사용
- ALL : 조건을 모두 만족하면 참
- ANY, SOME : 조건을 하나라도 만족하면 참(ANY와 SOME 같은 의미)
논리 연산
- AND : 둘 다 만족하면 참
- OR : 둘 중 하나만 만족해도 참
- NOT : 조건식 결과의 반대
비교 연산
- =, >, ≥, <, ≤, <>
Between 식
- BETWEEN : A ~ B 사이의 값이면 참(A, B 포함)
- LIKE : 문자 표현식과 패턴 값을 비교
- IS [NOT] NULL : NULL 인지 비교
컬렉션 식
- IS [NOT] EMPTY : 컬렉션에 값이 비어있는지 여부
- [NOT] MEMBER [OF] : 엔티티나 값이 컬렉션에 포함되어 있는지 여부
스칼라 식
- 단항 연산자(+, -), 사칙연산(+, -, *, /)
기타식 간단 예시
// IS NULL : 이름이 null이 아닌 Member 이름 조회
em.createQuery("select m.username from Member m where m.username is not null").getResultList();
// BETWEEN : 나이가 20 ~ 30인 Member 이름 조회
em.createQuery("select m.username from Member m where m.age between 20 and 30").getResultList();
// LIKE : 이름이 박으로 시작하는 Member 이름 조회
em.createQuery("select m.username from Member m where m.username like '박%'").getResultList();
// IN : 이름이 홍길동이나 임꺽정인 Member 이름 조회
em.createQuery("select m.username from Member m where m.username in ('홍길동', '임꺽정')".getResultList();
// EMPTY : 주문이 하나라도 있는 Member 이름 조회
em.createQuery("select m.username from Member m where m.orders is not empty").getResultList();
연산자 우선순위
- 경로 탐색 연산(.)
- 수학 연산(+, -, *, /)
- 비교 연산(Between 식, 컬렉션 식 포함)
- 논리 연산(AND, OR, NOT)
기본 함수
문자 함수
- CONCAT(문자1, 문자2, …) : 문자를 합한다.
- concat('A', 'B') = AB
- SUBSTRING(문자, 위치, [길이]) : 위치부터 시작해 길이만큼 문자를 구한다.
- substring('ABCDEF', 2, 3) = BCD
- TRIM([[LEADING | TRAILING | BOTH] [트림 문자] FROM] 문자) : 트림 문자를 제거한다.
- LEADING : 트림 문자의 왼쪽 제거
- TRAILING : 트림 문자의 오른쪽 제거
- BOTH : 트림 문자의 양쪽 제거(기본값)
- trim(’ ABC ‘) = ‘ABC’
- LOWER(문자) : 소문자로 변경
- lower(’ABC’) = ‘abc’
- UPPER(문자) : 대문자로 변경
- upper(’abc’) = ‘ABC’
- LENGTH(문자) : 문자 길이
- length(’abc’) = 3
- LOCATE(찾을 문자, 원본 문자, [검색 시작 위치]) : 검색 위치부터 문자를 검색한다.
- locate(’de’, ‘abcdef’) = 4
- locate(’d’, ‘abc’) = 0
수학 함수
- ABS(수학식) : 절댓값, abs(-10) = 10
- SQRT(수학식) : 제곱근, sqrt(4) = 2.0
- MOD(수학식, 나눌 수) : 나머지, mod(4, 3) = 1
- SIZE(컬렉션 값 연관 경로식) : 컬렉션의 크기, size(t.members)
- INDEX(별칭) : LIST 타입 컬렉션의 위치 값
- 컬렉션이 @OrderColumn을 사용하는 LIST 타입일 때만 사용 가능
- t.members m where index(m) > 3
사용자 정의 함수
하이버네이트는 사용 전 방언에 추가해야 한다.
사용하는 DB 방언을 상속받고, 사용자 정의 함수를 등록하여 사용한다.
group_concat이라는 함수가 있다고 가정한다.
public class MyH2Dialect extends H2Dialect {
public MyH2Dialect() {
registerFunction("group_concat", new StandardSQLFunction("group_concat", StandardBasicTypes.STRING));
}
}
- 사용하는 데이터베이스의 Dialect를 상속받는 클래스를 작성하여 생성자에서 registerFunction() 메서드를 통해 함수를 등록한다.
사용자 정의 함수 호출
select function('group_concat', m.username) from Member m
// 하이버네이트 사용시 가능
select group_concat(m.username) from Member m
조건식 - CASE
JPQL은 SQL과 마찬가지로 특정 조건에 따라 분기할 때 CASE 식을 사용한다.
CASE 4가지 종류
- 기본 CASE
- 단순 CASE
- COALESCE
- NULLIF
기본 CASE
select
case when m.age <= 10 then '학생요금'
when m.age >= 60 then '경로요금'
else '일반요금'
end
from Member m
단순 CASE
단순 CASE는 조건식을 사용할 수 없지만, 문법이 단순하다. (자바의 switch case 문과 비슷)
select
case t.name
when 'TeamA' then '인센티브110%'
when 'TeamB' then '인센티브120%'
else '인센티브105%'
end
from Team t
COALESCE
스칼라식을 차례대로 조회해서 null이 아니면 반환한다.
select coalesce(m.username, '이름 없는 회원') from Member m
- m.username이 null이면 ‘이름 없는 회원’을 반환
NULLIF
두 값이 같으면 null 반환, 다르면 첫 번째 값 반환
select NULLIF(m.username, '관리자') from Member m
- m.username이 ‘관리자’이면 null을 반환하고, null이 아니면 m.username 반환
반응형
'프레임워크(Framework) > JPA' 카테고리의 다른 글
[JPA] JPQL 페치 조인(Fetch join) - 객체지향 쿼리 언어 JPQL (8) (0) | 2022.12.20 |
---|---|
[JPA] JPQL 경로 표현식 - 객체지향 쿼리 언어 JPQL (7) (0) | 2022.12.19 |
[JPA] JPQL 서브 쿼리 - 객체지향 쿼리 언어 JPQL (5) (0) | 2022.12.17 |
[JPA] JPQL 조인(Join) - 객체지향 쿼리 언어 JPQL (4) (0) | 2022.12.16 |
[JPA] JPQL 페이징(Paging) API - 객체지향 쿼리 언어 JPQL (3) (0) | 2022.12.15 |