![[자바 ORM 표준 JPA 프로그래밍 - 기본편] 10. 객체 지향 쿼리 언어 1](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdi4u1G%2FbtsC8Ypd2TR%2FaJMKCfhfJuITlyeqQy9vD1%2Fimg.png)
인프런 김영한 강사님의 [자바 ORM 표준 JPA 프로그래밍 - 기본편] 을 수강하고 정리한 글입니다.
자바 ORM 표준 JPA 프로그래밍 - 기본편 강의 - 인프런
현업에서 실제로 JPA로 개발을 하고 있습니다. 그런 입장에서보면 지금 작성하고 있는 코드들이 어떻게 작동하는지 이해하는데 큰 도움을 주는 강의입니다. 다음은 제가 느낀 이 강의의 장점들
www.inflearn.com
📌 객체 지향 쿼리 언어 소개
✅ JPA가 지원하는 다양한 쿼리 방식
- JPQL
- JPA Creteria
- QueryDSL
- Native SQL
- JDBC API 직접 사용, MyBatis, SpringJdbcTemplate과 함께 사용
✅ JPQL 소개
JPA에서 제공하는 SQL을 추상화한 객체 지향 쿼리 언어
SQL과 문법이 유사하여, SELECT/FROM/WHERE/GROUP BY/HAVING/JOIN을 지원한다.
JPQL은 엔티티 객체를 대상으로 쿼리하고, SQL은 DB 테이블을 대상으로 쿼리한다는 것이 차이점이다.
JPQL은 결국 SQL로 변환된다.
// 검색
String jpql = "select m From Member m where m.name like '%hello%'";
List<Member> result = em.createQuery(jpql, Member.class).getResultList();
특정 DB SQL에 의존하지 않는다.
✅ Criteria 소개
문자가 아닌 자바 코드로 JPQL을 작성할 수 있다.
일종의 JPAL 빌더를 말한다.
그러나 너무 복잡하고 실용성이 떨어져서 권장하지 않는다.
✅ QueryDSL 소개
// JPQL
// select m from Member m where m.age > 18
JPAFactoryQuery query = new JPAQueryFactory(em);
QMember m = QMember.member;
List<Member> list = query.selectFrom(m)
.where(m.age.gt(18))
.orderBy(m.name.desc())
.fetch();
문자가 아닌 자바 코드로서 JPQL을 작성할 수 있는 JPQL 빌더이다.
컴파일 시점에 문법 오류를 찾을 수 있어 매우 좋다.
동적 쿼리를 작성하는 것이 매우 편리하다.
단순하고 쉬워서 실무에서 사용을 권장한다.
✅ Native SQL 소개
JPA가 제공하는 SQL을 직접 사용하는 방식이다.
JPQL로 해결이 안되는 경우에 사용한다.
✅ JDBC 직접 사용, SpringJdbcTemplate 등
JPA를 사용하면서 JDBC 커넥션, 스프링 JdbcTemplate, MyBatis 등을 함께 사용할 수 있다.
단, 영속성 컨텍스트를 적절한 시점에 강제로 플러시 해줘야 하는 번거로움이 있다.
📌 JPQL 기본 문법과 쿼리 API
✅ JPQL 문법
select m from Member as m where m.age > 18
엔티티와 속성은 대소문자 구분을 한다. (Member, age)
JPQL 키워드는 대소문자 구분을 하지 않는다. (SELECT, FROM, where)
엔티티 이름을 사용하고, 테이블 이름을 사용하지 않는다.
별칭(alias)는 필수다. (대신 as 키워드는 생략 가능하다.)
✅ TypeQuery, Query
TypeQuery : 반환 타입이 명확할 때 사용한다.
Query : 반환 타입이 명확하지 않을 때 사용한다.
TypeQuery<Member> query = em.createQuery("SELECT m FROM Member m", Member.class);
Query query = em.createQuery("SELECT m.username, m.age from Member m");
✅ 결과 조회 API
query.getResultList() : 결과가 하나 이상일 때, 리스트 반환
query.getSingleResult() : 결과가 정확하게 하나, 단일 객체 반환
✅ 파라미터 바인딩
SELECT m FROM Member m where m.username=:username
query.setParameter("username", usernameParam);
SELECT m FROM Member m where m.username=?1
query.setParameter(1, usernameParam);
📌 프로젝션 (SELECT)
✅ 프로젝션
SELECT 절에 조회할 대상을 지정하는 것을 말한다.
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 // 스칼라 타입 프로젝션
프로젝션으로 여러 값을 조회하고 싶다면
1. Query 타입으로 조회
2. Object[] 타입으로 조회
3, new 명령어로 조회
📌 페이징
✅ 페이징 API
JPA는 페이징을 아래 두 API로 추상화한다.
setFirstResult(int startPosition) : 조회 시작 위치 (0부터 시작)
setMaxResults(int maxResult) : 조회할 데이터 수
// 페이징 쿼리
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 FROM Member m [INNER] JOIN m.team t
// 외부 조인
SELECT m FROM Member m LEFT [OUTER] JOIN m.team t
// 세타 조인
SELECT count(m) FROM Member m, Team t WHERE m.username = t.name
✅ 조인 : ON 절
on 절을 활용하면 조인 대상을 필터링하고 연관관계 없는 엔티티 외부 조인이 가능하다.
📌 서브 쿼리
✅ 서브 쿼리 지원 함수
[NOT]EXISTS(subquery) : 서브쿼리에 결과가 존재하면 참
[NOT]IN(subquery) : 서브쿼리 결과 중 하나라도 같은 것이 있다면 참
FROM 절의 서브 쿼리는 현재 JPQL에서 불가능하다.
'Backend > JPA' 카테고리의 다른 글
[실전! 스프링 데이터 JPA] 1. 공통 인터페이스 기능 (0) | 2024.01.05 |
---|---|
[자바 ORM 표준 JPA 프로그래밍 - 기본편] 11. 객체지향 쿼리 언어 2 (1) | 2024.01.05 |
[자바 ORM 표준 JPA 프로그래밍 - 기본편] 9. 값 타입 (0) | 2024.01.05 |
[자바 ORM 표준 JPA 프로그래밍 - 기본편] 8. 프록시와 연관관계 관리 (0) | 2024.01.05 |
[자바 ORM 표준 JPA 프로그래밍 - 기본편] 7. 고급 매핑 (0) | 2024.01.04 |
개발자가 되고 싶어요.