김영한 님의 "자바 ORM 표준 JPA 프로그래밍" 책을 정리한 포스팅 입니다.
1. JPQL
- 객체 지향 쿼리
- SQL 추상화
- 실행 시점에 SQL 문을 생성하여 요청함
예제) JPQL ➡️ SQL
더보기
// 쿼리 생성
String jpql = "select m from Member as m where m.username = 'kim'";
List<Member> resultList = em.createQuery(jpql, Member.class).getResultList();
특징
구분 | 설명 |
기본 문법 |
SQL과 유사한 문법 사용 (SELECT, FROM, WHERE, GROUP BY, HAVING, ORDER BY 등)
- 엔티티명과 필드 사용, 별칭 필수 |
쿼리 객체 API |
- TypedQuery: 반환 타입 명확할 때
- Query: 반환 타입 명확하지 않을 때 |
결과 조회 |
- getResultList() : 결과 리스트 반환
- getSingleResult() : 단일 결과, 예외 발생 가능성 있음 |
파라미터 바인딩 | - 이름 기반 :name - 위치 기반 ?1, ?2 |
프로젝션 |
SELECT 절에 조회할 대상을 지정하는 것
- 엔티티, 임베디드, 스칼라 타입 선택 가능 - ex) DTO 매핑 |
페이징 API |
setFirstResult(int), setMaxResults(int) 사용
|
집합 함수 |
COUNT, SUM, AVG, MAX, MIN 지원. NULL은 무시됨
|
GROUP BY / HAVING |
그룹화 및 조건 필터링
|
ORDER BY |
정렬 시 사용. AS 별칭 지정하여 정렬 가능
|
조인 | - 내부 조인 (LAZY) - 외부 조인 (LAZY) - 컬렉션 조인 (LAZY) - 페치 조인 (FETCH) |
예제) 기본 쿼리
더보기
@Test
@Transactional
void select() {
String jpql = "select u from User as u where u.name = 'updated'";
User result = entityManager.createQuery(jpql, User.class).getSingleResult();
assertEquals(result.getName(), "updated");
assertEquals(result.getId(), 1);
}
예제) 쿼리 객체 API
더보기
@Test
@Transactional
void typedQuery() {
String jpql = "select u from User as u where u.name = 'updated'";
TypedQuery<User> query = entityManager.createQuery(jpql, User.class);
User result = query.getSingleResult();
assertEquals(result.getName(), "updated");
assertEquals(result.getId(), 1);
}
@Test
@Transactional
void query() {
String jpql = "select u from User as u where u.name = 'updated'";
Query query = entityManager.createQuery(jpql, User.class);
List result = query.getResultList();
assertTrue(!result.isEmpty());
}
예제) 결과 조회 + 파라미터 바인딩
더보기
List<Member> members = em.createQuery("SELECT m FROM Member m where m.username = :username", Member.class)
.setParameter("username", username)
.getResultList();
List<Member> members = em.createQuery("SELECT m FROM Member m where m.username = ?1", Member.class)
.setParameter(1, username)
.getResultList();
예제) 프로젝션
더보기
@Test
@Transactional
void projection_scala() {
String jpql = "select u from User as u where u.name = 'updated'";
Query query = entityManager.createQuery(jpql, User.class);
List result = query.getResultList();
assertTrue(!result.isEmpty());
}
@Test
@Transactional
void projection_dto() {
String jpql = "select new jpql.UserDto(u.id, u.name) from User as u where u.name = 'updated'";
TypedQuery<UserDto> query = entityManager.createQuery(jpql, UserDto.class);
UserDto result = query.getSingleResult();
assertEquals(result.getName(), "updated");
assertEquals(result.getId(), 1);
}
예제) 페이징 API
더보기
@Test
@Transactional
void paging() {
String jpql = "select u from User as u order by u.id DESC";
TypedQuery<User> query = entityManager.createQuery(jpql, User.class);
query.setFirstResult(2); // offset
query.setMaxResults(10); // 결과 셋 최대 크기
List<User> result = query.getResultList();
}
예제) 집계 함수
더보기
@Test
@Transactional
void aggregation() {
String jpql = "select count(u), max(u.name) from User as u";
TypedQuery<Object[]> query = entityManager.createQuery(jpql, Object[].class);
List<Object[]> result = query.getResultList();
Object[] row = result.get(0);
System.out.println("count: " + row[0]);
System.out.println("max: " + row[1]);
}
예제) GROUP BY / HAVING
더보기
@Test
@Transactional
void grouping() {
String jpql = "select u.name, count(u.id) from User as u group by u.name";
TypedQuery<Object[]> query = entityManager.createQuery(jpql, Object[].class);
List<Object[]> result = query.getResultList();
for (Object[] row : result) {
System.out.println("count: " + row[0]);
System.out.println("max: " + row[1]);
System.out.println();
}
}
예제) 조인
더보기
내부 조인
@Test
@Transactional
void join() {
String jpql = "select u from User u INNER JOIN u.team t";
TypedQuery<User> query = entityManager.createQuery(jpql, User.class);
List<User> result = query.getResultList();
for (User row : result) {
System.out.println("id: " + row.getId());
System.out.println("name: " + row.getName());
System.out.println("team id: " + row.getTeam().getName());
System.out.println();
}
}
컬렉션 조인
@Test
@Transactional
void collection_join() {
String jpql = "select u from Team t JOIN t.members u WHERE t.name = :teamName";
TypedQuery<User> query = entityManager.createQuery(jpql, User.class)
.setParameter("teamName", "gsw");
List<User> result = query.getResultList();
for (User row : result) {
System.out.println("id: " + row.getId());
System.out.println("name: " + row.getName());
System.out.println("team id: " + row.getTeam().getName());
System.out.println();
}
}
페치 조인
@Test
@Transactional
void fetch_join() {
String jpql = "select u from User u JOIN FETCH u.team t";
TypedQuery<User> query = entityManager.createQuery(jpql, User.class);
List<User> result = query.getResultList();
for (User row : result) {
System.out.println("id: " + row.getId());
System.out.println("name: " + row.getName());
System.out.println("team id: " + row.getTeam().getName());
System.out.println();
}
}
'Spring > Spring Data JPA' 카테고리의 다른 글
[자바 ORM 표준 JPA 프로그래밍] 10-4. 객체지향 쿼리 언어: Native SQL (0) | 2025.04.24 |
---|---|
[자바 ORM 표준 JPA 프로그래밍] 10-2. 객체지향 쿼리 언어: Criteria (0) | 2025.04.24 |
[Spring Data JPA] 3-4. Specifications (0) | 2024.08.03 |
[Spring Data JPA] 4-1. Spring Data Extensions (1) (0) | 2024.08.02 |
[Spring Data JPA] 3-3. Custom Repository Implementations (0) | 2024.08.02 |