🧩 Embedded Type (임베디드 타입)이란?
- JPA는 새로운 값 타입을
@Embeddable,@Embedded로 직접 정의 가능- 임베디드 타입도
int,String처럼 값 타입- 재사용성↑, 응집도↑, 단일 책임 원칙 준수
📌 예시 코드:
@Entity
public class Tutor {
@Id @GeneratedValue
private Long id;
private String name;
// Embedded 사용
@Embedded
private Period workPeriod;
}
@Embeddable
public class Period {
@Temporal(TemporalType.DATE)
Date startDate;
@Temporal(TemporalType.DATE)
Date endDate;
public boolean isWork(Date date) {
return (startDate == null || !date.before(startDate)) &&
(endDate == null || !date.after(endDate));
}
}
✅ 장점
🎯 Projection (프로젝션)이란?
- 엔티티 전체가 아닌 특정 필드만 조회
→ 필요한 데이터만 가져와 성능 최적화 + 네트워크 비용 절감
📌 종류
1. Entity 프로젝션
List<Tutor> tutors = em.createQuery("select t from Tutor t", Tutor.class).getResultList();
JOIN 사용 가능⚠️ 묵시적 JOIN(자동)은 SQL 예측 어려움 → 명시적 JOIN 권장
Company c1 = em.createQuery("select t.company from Tutor t", Company.class).getSingleResult(); // 묵시적
Company c2 = em.createQuery("select t from Tutor t join t.company", Company.class).getSingleResult(); // 명시적
2. Embedded 프로젝션
List<Period> list = em.createQuery("select t.period from Tutor t", Period.class).getResultList();
select period from Period ❌ (임베디드 자체를 바로 조회 불가)select t from Tutor t where t.period.startDate < ?@MappedSuperclass) 활용 시 더 직관적3. Scalar(스칼라) 프로젝션
List resultList = em.createQuery("select t.name, t.age from Tutor t").getResultList();
Object[] result = (Object[]) resultList.get(0);
System.out.println(result[0] + ", " + result[1]);
📊 Projection 정리
| 종류 | 설명 | 특징 |
|---|---|---|
| Entity | 엔티티 전체 조회 | 영속성 컨텍스트 관리됨 |
| Embedded | @Embeddable 타입 조회 | 조건문에서도 활용 가능 |
| Scalar | 특정 필드만 조회 | 배열(Object\[]) 또는 DTO로 매핑 가능 |
📑 Paging (페이징 처리)
- 대량 데이터 중 일부만 가져오기 위해 결과 범위를 제한하는 기능
📄 JPQL 페이징 메서드
setFirstResult(int startPosition) → 조회 시작 위치setMaxResults(int maxResult) → 조회할 데이터 수📌 예시 코드:
List<Tutor> tutors = em.createQuery(
"select t from Tutor t order by t.age desc", Tutor.class)
.setFirstResult(5) // 6번째부터
.setMaxResults(10) // 10개 조회
.getResultList();
for (Tutor t : tutors) {
System.out.println(t.getId() + ", " + t.getName() + ", " + t.getAge());
}
limit, ORACLE → ROWNUM 사용🧠 요약 정리
| 구분 | 핵심 내용 |
|---|---|
| Embedded Type | @Embeddable, @Embedded로 값 타입 정의 · 여러 엔티티에서 재사용 가능 · 응집도 ↑, 단일 책임 원칙 준수 · 독립적 로직 작성 가능 |
| Projection 정의 | 엔티티 전체가 아닌 특정 필드만 조회 → 성능 최적화 & 네트워크 비용 절감 |
| Entity Projection | select t from Tutor t · 영속성 컨텍스트 관리됨 · 연관 엔티티는 JOIN으로 조회 · ⚠ 묵시적 JOIN 대신 명시적 JOIN 권장 |
| Embedded Projection | select t.period from Tutor t · Embedded 자체만 단독 조회 불가 · 조건문에서 활용 가능 ( t.period.startDate < ?) · 상속( @MappedSuperclass)이 더 직관적 |
| Scalar Projection | select t.name, t.age from Tutor t · 단일/여러 필드만 조회 · Object[] 반환, DTO 매핑 가능 |
| Paging | 대량 데이터 중 일부만 조회 · setFirstResult(start) → 시작 위치 · setMaxResults(max) → 조회 개수 제한 · DB 방언에 맞게 페이징 SQL 변환 (MySQL=LIMIT, Oracle=ROWNUM) |