💡 JPQL 객체지향 쿼리
다양한 쿼리 지원
- JPQL
- JPA Criteria
- QueryDSL
- 동적 쿼리 생성의 편리함
- 실무 사용 권장
- Native SQL
- JPQL로 해결할 수 없는 DB 의존적인 기능을 사용할 때
- ex: Oracle CONNECT BY, SQL HINT
- createNativeQuery() 사용
- JDBC API 직접 사용, MyBatis, SpringJdbcTemplate 함께 사용
- 영속성 컨텍스트를 적잘한 시점에 강제로 flush가 필요하다.
- ex: JPA를 우회해서 SQL을 실행하기 직전 수동 flush
- JPA를 사용하면서 JDBC 커넥션을 직접 사용하거나, JDBC Template, MyBatis 등 혼용 가능
소개
- Java Persistence Query Language
- 가장 단순한 조회 방법
- EntityManager.find()
- 객체 그래프 탐색
- (a.getB().getC())로 get get get 하면서 계속 찾아다닐 수 없다.
기타
- 서브 쿼리 지원
- EXISTS, IN
- BETWEEN, LIKE, IS NULL
특징
- JPA를 사용하면 엔티티 객체를 중심으로 개발
- 문제는 검색 쿼리
- 검색을 할 때도 테이블이 아닌 엔티티 객체를 대상으로 검색을 해야한다.
- DB를 몰라야 한다. 자바 코드에서 멤버 테이블이 있구나 보다, 멤버 객체가 있구나라는
생각을 가지고 개발해야 한다.
- DB를 몰라야 한다. 자바 코드에서 멤버 테이블이 있구나 보다, 멤버 객체가 있구나라는
- 근데, 모든 DB 데이터를 객체로 변환해서 검색하는 것은 불가능하다.
- 애플리케이션이 필요한 데이터만 DB에서 불러오려면 결국 검색 조건이 포함된 SQL이 필요하다.
- 그래서 JPA는 SQL을 추상화한 JPQL이라는 객체 지향 쿼리 언어를 제공한다.
- SQL과 문법이 유사하고, SELECT, FROM, WHERE, GROUP BY, HAVING, JOIN등을 지원한다.
- JPQL은 엔티티 객체를 대상으로 쿼리를 질의하고
- SQL은 데이터베이스 테이블을 대상으로 쿼리를 질의한다.
- ex) 객체를 대상으로 JPQL 작성
//검색
String jpql= "select m From Member m where m.name like '%hello%'";
List<Member> result = em.createQuery(jpql, Member.class).getResultList();
- 위의 JPQL에 의해 변환되어(데이터베이스 방언을 참조해서 DB에 맞는 쿼리로) 실행된 SQL
select
m.id as id,
m.age as age,
m.USERNAME as USERNAME,
m.TEAM_ID as TEAM_ID
from
Member m
where
m.age>18
- 테이블이 아닌 객체를 대상으로 검색하는 객체지향 쿼리라고 이해하면 되며,
- SQL을 추상화해서 특정 데이터베이스 SQL에 의존하지 않는다.
- JPQL을 한마디로 정의하면 객체 지향 SQL 이다.
💡 JPQL 기본 함수
- CONCAT : 문자 더하기
- SUBSTRING : 자르기
- TRIM : 공백 제거
- LOWER, UPPER : 대소문자
- LENGTH : 길이
- LOCATE : 위치
- ABS, SQRT, MOD : Math
- SIZE, INDEX (JPA 용도) : 컬렉션의 크기
사용자 정의 함수 호출
- 하이버네이트는 사용전 방언에 추가해야 한다.
- DB에 커스텀 Function 만든 후 사용
public class MyH2Dialect extends H2Dialect {
public MyH2Dialect() {
registerFunction("customDB", new StandardSQLFunction("customDB", StandardBasicTypes.String))
}
}
select function ('customDB', i.name) from Item i
💡 문법
select_문 :: =
select_절
from_절
[where_절]
[groupby_절]
[having_절]
[orderby_절]
# 벌크연산
update_문 :: = update_절 [where_절]
delete_문 :: = delete_절 [where_절]
- 몇가지 유의 사항은 존재 한다.
- from절에 들어가는 것은 객체이다.
- select m from Member m where m.age > 8
- 엔티티와 속성은 대소문자를 구분
- 예를 들면, Member 엔티티와 username 필드
- JPQL 키워드는 대소문자 구분 안함
- SELECT, FROM, where
- 엔티티 이름을 사용한다. 테이블 이름이 아니다
- 엔티티명 Member
- 별칭은 필수이다, as 생략가능
- Member의 별칭 m
JPQL 타입 표현
문자 : 'HELLO', 'She''s'
숫자 : 10L(Long), 10D(Double) , 10F(Float)
Boolean : TRUE, FALSE
ENUM : org.MemberType.Admin (패키지명 포함), 파라미터 바인딩 사용 권장
엔티티 타입 : TYPE(m) - Member (상속 관계에서 사용)
기타 표현
- SQL과 문법이 같다
- EXIST, IN, AND, OR, NOT
- =, >, >=, <, <=, <>
- BETWEEN, LIKE, IS NULL
집합과 정렬
- 기본적인 집합 명령어 다 동작 한다.
select
COUNT(m), //회원수
SUM(m.age), //나이 합
AVG(m.age), //평균 나이
MAX(m.age), //최대 나이
MIN(m.age) //회소 나이
from Member m
- GROUP BY, HAVING
- ORDER BY
💡 조건식 - CASE
조건식에는 기본 CASE, 단순 CASE가 있다.'
기본 CASE
String query =
"select " +
"case " +
"when m.age <= 10 then '학생요금' " +
"when m.age >= 60 then '경로요금' " +
"else '일반요금' " +
"end " +
"from Member m";
단순 CASE
String query =
"select " +
"case t.name " +
"when '팀A' then '인센티브110%' " +
"when '팀B' then '인센티브120%' " +
"else '인센티브105%' " +
"end " +
"from Team t";
COALESCE
하나씩 조회해서 null이 아니면 반환
select coalesce(m.username, '이름 없는 회원') from Member m
NULLIF
두 값이 같으면 null 반환, 다르면 첫번째 값 반환
select NULLIF(m.username, '관리자') from Member m
💡 Reference
- 자바 ORM 표준 JPA 프로그래밍
- 저자 직강 - https://www.youtube.com/watch?v=WfrSN9Z7MiA&list=PL9mhQYIlKEhfpMVndI23RwWTL9-VL-B7U
'Database > JPQL' 카테고리의 다른 글
JQPL 경로표현식 (2) | 2023.03.19 |
---|---|
JPQL Type Query & Sub Query (0) | 2023.03.11 |
JPQL Paging API & Search Result API (0) | 2023.03.11 |
JPQL Projection (0) | 2023.03.11 |
JPQL Parameter Binding (0) | 2023.03.11 |