JPA Programming Basic

JPA Programming Basic

μ˜ν•œλ‹˜μ˜ μžλ°” ORM ν‘œμ€€ JPA ν”„λ‘œκ·Έλž˜λ° - 기본편arrow-up-right κ°•μ˜λ₯Ό μš”μ•½ν•œ λ‚΄μš©μž…λ‹ˆλ‹€.

Projectarrow-up-right

Intro

JPA

  • Java Persistence API

  • μžλ°” μ§„μ˜μ˜ ORM 기술 ν‘œμ€€ (μΈν„°νŽ˜μ΄μŠ€μ˜ λͺ¨μŒ)

    • κ΅¬ν˜„μ²΄λ‘œλŠ” Hibernate, EclipseLink, DataNucleus..

  • Applicationκ³Ό JDBC μ‚¬μ΄μ—μ„œ λ™μž‘

ROM

  • Object-Relational Mapping

  • ObjectλŠ” ObjectλŒ€λ‘œ, RDBMSλŠ” RDBMSλŒ€λ‘œ 섀계

  • ORM ν”„λ ˆμž„μ›Œν¬κ°€ μ€‘κ°„μ—μ„œ λ§€ν•‘

EntityManagerFactory

  • persistence.xml μ„€μ • 정보 확인 ν›„ persistence-unit name 에 λ§žλŠ” EntityManagerFactory 생성

  • Web Server κ°€ μƒμ„±λ˜λŠ” μ‹œμ μ— ν•˜λ‚˜λ§Œ μƒμ„±ν•΄μ„œ μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ „μ²΄μ—μ„œ 곡유

    EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");

EntityManager

  • μš”μ²­ κ±΄λ§ˆλ‹€ 생성

  • μ“°λ ˆλ“œκ°„ κ³΅μœ ν•˜λ©΄ μ•ˆ 되고, μ‚¬μš© ν›„ μ’…λ£Œ

EntityTransaction

  • JPA의 λͺ¨λ“  데이터 변경은 νŠΈλžœμ μ…˜ μ•ˆμ—μ„œ μ‹€ν–‰

μ˜μ†μ„± 관리

μ˜μ†μ„± μ»¨ν…μŠ€νŠΈ

PersistenceContext (μ—”ν‹°ν‹°λ₯Ό 영ꡬ μ €μž₯ν•˜λŠ” ν™˜κ²½)

  • EntityManager λ₯Ό 톡해 PersistenceContext 에 μ ‘κ·Ό

    • EntityManager, PersistenceContext λŠ” 1:1, N:1 관계 쑴재

  • μ—”ν‹°ν‹° 생λͺ…μ£ΌκΈ°

    • λΉ„μ˜μ† (new / transient)

      • μ˜μ†μ„± μ»¨ν…μŠ€νŠΈμ™€ μ „ν˜€ 관계가 μ—†λŠ” μƒˆλ‘œμš΄ μƒνƒœ

    • μ˜μ† (managed)

      • μ˜μ†μ„± μ»¨ν…μŠ€νŠΈμ— κ΄€λ¦¬λ˜λŠ” μƒνƒœ

    • μ€€μ˜μ† (detached)

      • μ˜μ†μ„± μ»¨ν…μŠ€νŠΈμ— μ €μž₯λ˜μ—ˆλ‹€κ°€ λΆ„λ¦¬λœ μƒνƒœ

    • μ‚­μ œ (removed)

      • μ‚­μ œλœ μƒνƒœ

.

μ˜μ†μ„± μ»¨ν…μŠ€νŠΈμ˜ 이점

  • 1μ°¨ μΊμ‹œμ—μ„œμ˜ 쑰회

    • μ‚¬μš©μžμ˜ ν•˜λ‚˜μ˜ μš”μ²­-응닡(ν•˜λ‚˜μ˜ νŠΈλžœμ μ…˜) λ‚΄μ—μ„œλ§Œ νš¨κ³Όκ°€ μžˆμœΌλ―€λ‘œ μ„±λŠ₯ 이점을 κΈ°λŒ€ν•˜μ§€λŠ” μ•ŠμŒ.

    • μ—”ν‹°ν‹° 쑰회 μ‹œ λ¨Όμ € 1μ°¨ μΊμ‹œμ—μ„œ 쑰회 ν›„, 없을 경우 DBμ—μ„œ 쑰회

  • μ˜μ† μ—”ν‹°ν‹°μ˜ 동일성(identity) 보μž₯

    • 1μ°¨ μΊμ‹œλ‘œ 반볡 κ°€λŠ₯ν•œ 읽기(REPEATABLE READ) λ“±κΈ‰μ˜ νŠΈλžœμž­μ…˜ 격리 μˆ˜μ€€μ„ λ°μ΄ν„°λ² μ΄μŠ€κ°€ μ•„λ‹Œ μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ°¨μ›μ—μ„œ 제곡

  • νŠΈλžœμž­μ…˜μ„ μ§€μ›ν•˜λŠ” μ“°κΈ° μ§€μ—°(transactional write-behind)

    • Queryλ₯Ό μŒ“μ•„ 두닀가 transaction.commit() 을 ν•˜λŠ” μˆœκ°„ λ°μ΄ν„°λ² μ΄μŠ€μ— Query 전솑

  • λ³€κ²½ 감지(Dirty Checking)

    • transaction.commit() μ‹œμ μ— 엔티티와 μŠ€λƒ…μƒ·(처음 읽어 온 μ—”ν‹°ν‹° μƒνƒœ) 비ꡐ ν›„ 변경이 κ°μ§€λ˜λ©΄ Update Query λ₯Ό μ“°κΈ° μ§€μ—° SQL μ €μž₯μ†Œμ— μ €μž₯

    • 이후 DB에 Query 전솑 및 Commit

  • μ§€μ—° λ‘œλ”©(Lazy Loading)

.

Flush

μ˜μ†μ„± μ»¨ν…μŠ€νŠΈμ˜ λ³€κ²½λ‚΄μš©μ„ λ°μ΄ν„°λ² μ΄μŠ€μ— λ°˜μ˜ν•˜λŠ” μ—­ν• 

λ°œμƒ μ‹œμ 

  • λ³€κ²½ 감지

  • μ“°κΈ° μ§€μ—° SQL μ €μž₯μ†Œμ˜ 쿼리λ₯Ό λ°μ΄ν„°λ² μ΄μŠ€μ— 전솑 (CUD Query)

호좜 방법

  • 직접 호좜 : em.flush()

  • μžλ™ 호좜 : νŠΈλžœμž­μ…˜ 컀밋, JPQL 쿼리 μ‹€ν–‰

μ—”ν‹°ν‹° λ§€ν•‘

객체와 ν…Œμ΄λΈ”

객체와 ν…Œμ΄λΈ” λ§€ν•‘

  • @Entity: JPAκ°€ κ΄€λ¦¬ν•˜λŠ” 클래슀 (κΈ°λ³Έ μƒμ„±μž ν•„μˆ˜)

  • @Table: 엔티티와 λ§€ν•‘ν•  ν…Œμ΄λΈ” μ§€μ •

ν•„λ“œμ™€ 컬럼 λ§€ν•‘

  • @Column

κΈ°λ³Έ ν‚€ λ§€ν•‘

  • @Id

연관관계 λ§€ν•‘

  • @ManyToOne

  • @JoinColumn

.

λ°μ΄ν„°λ² μ΄μŠ€ μŠ€ν‚€λ§ˆ μžλ™ 생성

@Entityκ°€ μžˆλŠ” 클래슀 DDL을 μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ‹€ν–‰ μ‹œμ μ— μžλ™ 생성 (개발 ν™˜κ²½μ—μ„œλ§Œ μ‚¬μš©)

  • create: κΈ°μ‘΄ν…Œμ΄λΈ” μ‚­μ œ ν›„ λ‹€μ‹œ 생성 (DROP + CREATE)

  • create-drop: create와 κ°™μœΌλ‚˜ μ’…λ£Œμ‹œμ μ— ν…Œμ΄λΈ” DROP

  • update: λ³€κ²½λΆ„λ§Œ 반영(운영DBμ—λŠ” μ‚¬μš©ν•˜λ©΄ μ•ˆλ¨)

  • validate 엔티티와 ν…Œμ΄λΈ”μ΄ 정상 λ§€ν•‘λ˜μ—ˆλŠ”μ§€λ§Œ 확인

  • none: μ‚¬μš©ν•˜μ§€ μ•ŠμŒ

주의

  • 운영 μž₯λΉ„μ—λŠ” μ ˆλŒ€ create, create-drop, update μ‚¬μš©ν•˜λ©΄ μ•ˆλ¨.

    • 개발 초기 λ‹¨κ³„λŠ” create λ˜λŠ” update

    • ν…ŒμŠ€νŠΈ μ„œλ²„λŠ” update λ˜λŠ” validate

    • μŠ€ν…Œμ΄μ§•κ³Ό 운영 μ„œλ²„λŠ” validate λ˜λŠ” none

.

ν•„λ“œμ™€ 컬럼

.

κΈ°λ³Έ ν‚€

  • @Id : 직접 ν• λ‹Ήν•  경우

  • @GeneratedValue : μžλ™ 생성할 경우

    • AUTO : 방언에 따라 μžλ™ μ§€μ • (default)

    • IDENTITY : λ°μ΄ν„°λ² μ΄μŠ€μ— μœ„μž„ (MYSQL)

      • 주둜 MySQL, PostgreSQL, SQL Server, DB2 μ—μ„œ μ‚¬μš©

      • μ°Έκ³ ) DB INSERT Query μ‹€ν–‰ 후에 ID 값을 μ•Œ 수 μžˆμœΌλ―€λ‘œ, em.persist() μ‹œμ μ— μ¦‰μ‹œ INSERT Query μ‹€ν–‰ 및 DB μ‹λ³„μž 쑰회

    • SEQUENCE : λ°μ΄ν„°λ² μ΄μŠ€ μ‹œν€€μŠ€ 였브젝트 μ‚¬μš© (ORACLE, @SequenceGenerator)

      • 주둜 였라클, PostgreSQL, DB2, H2 μ—μ„œ μ‚¬μš©

    • TABLE : ν‚€ μƒμ„±μš© ν…Œμ΄λΈ” μ‚¬μš©, (λͺ¨λ“  DB, @TableGenerator)

Long Type + λŒ€μ²΄ν‚€ + ν‚€ μƒμ„±μ „λž΅ μ‚¬μš© ꢌμž₯

AUTO & IDENTITY

SEQUENCE

allocationSize

  • μ‹œν€€μŠ€λ₯Ό ν•œ 번 ν˜ΈμΆœν•  λ•Œ μ¦κ°€ν•˜λŠ” 수 (μ„±λŠ₯ μ΅œμ ν™”μ— μ‚¬μš©, default. 50)

    • μ›Ή μ„œλ²„λ₯Ό λ‚΄λ¦¬λŠ” μ‹œμ μ— λ©”λͺ¨λ¦¬μ— μ €μž₯λ˜μ–΄μžˆλ˜ μ‹œν€€μŠ€λ“€μ΄ λ‚ λΌκ°€μ„œ ꡬ멍이 μƒκΈ°λ―€λ‘œ, 50~100이 적절

    • DB μ‹œν€€μŠ€ 값이 ν•˜λ‚˜μ”© μ¦κ°€ν•˜λ„λ‘ μ„€μ •λ˜μ–΄ μžˆλ‹€λ©΄, 이 값을 λ°˜λ“œμ‹œ 1둜 μ„€μ •

  • ex) 초기 1 ~ 51 κΉŒμ§€ 쑰회, 이후 μ‹œν€€μŠ€λŠ” DBμ—μ„œ μ‘°νšŒν•˜μ§€ μ•Šκ³  λ©”λͺ¨λ¦¬μƒμ—μ„œ 쑰회

    • λ©”λͺ¨λ¦¬μ—μ„œ μ‹œν€€μŠ€ 51을 λ§Œλ‚˜λŠ” μˆœκ°„ λ‹€μ‹œ DBμ—μ„œ 쑰회(next call)

  • 미리 μ‹œν€€μŠ€ 값을 μ˜¬λ €λ‘λ―€λ‘œ λ™μ‹œμ„± λ¬Έμ œκ°€ λ˜μ§€ μ•ŠμŒ

  • 이 뢀뢄은 Table μ „λž΅λ„ μœ μ‚¬

연관관계 λ§€ν•‘

JPAλŠ” 객체의 참쑰와 ν…Œμ΄λΈ”μ˜ μ™Έλž˜ ν‚€λ₯Ό λ§€ν•‘

λ°©ν–₯(Direction)

단방ν–₯

μ–‘λ°©ν–₯

  • 객체의 μ–‘λ°©ν–₯ κ΄€κ³„λŠ” 사싀 μ„œλ‘œ λ‹€λ₯Έ 단뱑ν–₯ 관계 2κ°œλΌλŠ” 사싀.

    • 객체λ₯Ό μ–‘λ°©ν–₯으둜 μ°Έμ‘°ν•˜λ €λ©΄ 단방ν–₯ 연관관계λ₯Ό 2개 λ§Œλ“€μ–΄μ•Ό 함

  • ν…Œμ΄λΈ”μ€ μ™Έλž˜ ν‚€ ν•˜λ‚˜λ‘œ 두 ν…Œμ΄λΈ”μ˜ 연관관계λ₯Ό 관리

μ—°κ΄€κ΄€κ³„μ˜ 주인(Owner)

μ™Έλž˜ν‚€λ₯Ό κ΄€λ¦¬ν•˜λŠ” μ°Έμ‘°

μ–‘λ°©ν–₯ λ§€ν•‘ κ·œμΉ™

  • 관계λ₯Ό κ°–λŠ” 두 객체 쀑 ν•˜λ‚˜μ˜ 객체λ₯Ό μ—°κ΄€κ΄€κ³„μ˜ 주인으둜 μ§€μ •

    • μ—°κ΄€κ΄€κ³„μ˜ 주인만이 μ™Έλž˜ ν‚€λ₯Ό 관리(등둝, μˆ˜μ •)ν•˜κ³ , 주인이 μ•„λ‹Œ μͺ½μ€ 쑰회만 κ°€λŠ₯

    • 주인이 μ•„λ‹Œ 객체의 ν•„λ“œμ— mappedBy μ†μ„±μœΌλ‘œ 주인 ν•„λ“œλ₯Ό μ§€μ •

  • μ—°κ΄€κ΄€κ³„μ˜ 주인은 λ‹€(N:1)에 ν•΄λ‹Ήν•˜λŠ” 객체μͺ½μ΄ 갖도둝(μ™Έλž˜ν‚€λ₯Ό κ°–λŠ” ν…Œμ΄λΈ” κΈ°μ€€)

    • μ—°κ΄€κ΄€κ³„μ˜ 주인에 κ°’ μ„€μ •ν•˜κΈ°

    • 연관관계 편의 λ©”μ†Œλ“œλ₯Ό μƒμ„±ν•˜λŠ” 것이 편리

  • μ–‘λ°©ν–₯ λ§€ν•‘μ‹œμ— λ¬΄ν•œ λ£¨ν”„λ‘œ μΈν•œ StackOverflow μ‘°μ‹¬ν•˜κΈ°

    • toString(), lombok, JSON 생성 라이브러리(=> Controller DTO λ°˜ν™˜μœΌλ‘œ ν•΄κ²°)

단방ν–₯ λ§€ν•‘λ§ŒμœΌλ‘œλ„ 연관관계 맀핑은 μ™„λ£Œλœ μƒνƒœ.

μΆ”ν›„ μ—­λ°©ν–₯ 탐색이 ν•„μš”ν•  κ²½μš°μ— μΆ”κ°€ν•˜κΈ°!(ν…Œμ΄λΈ”μ— 영ν–₯ X)

닀쀑성(Multiplicity)

λ‹€λŒ€μΌ(N:1) - @ManyToOne

  • ν…Œμ΄λΈ” μ™Έλž˜ν‚€ κΈ°μ€€μœΌλ‘œ μ—°κ΄€λœ μ°Έμ‘°λ₯Ό μ„€μ •(N이 μ—°κ΄€κ΄€κ³„μ˜ 주인)

  • μ–‘λ°©ν–₯ 연결을 ν•  경우, λ°˜λŒ€ 객체에도 OneToMany λ°©ν–₯ μ„€μ • μΆ”κ°€(쑰회만 κ°€λŠ₯)

μΌλŒ€λ‹€(1:N) - @OneToMany

  • μΌλŒ€λ‹€ 단방ν–₯

    • μœ„μ™€ λ°˜λŒ€ μΌ€μ΄μŠ€λ‘œ 일(1)이 μ—°κ΄€κ΄€κ³„μ˜ 주인이 될 경우, A(1) ν…Œμ΄λΈ” μ—…λ°μ΄νŠΈλ₯Ό μ‹œλ„ν–ˆμ§€λ§Œ B(N) ν…Œμ΄λΈ”λ„ ν•¨κ»˜ μ—…λ°μ΄νŠΈλ₯Ό ν•΄μ•Όν•˜λŠ” μƒν™©μœΌλ‘œ μ—¬λŸ¬ 이슈 λ°œμƒ μš”μ†Œκ°€ 생김

      • μ—”ν‹°ν‹°κ°€ κ΄€λ¦¬ν•˜λŠ” μ™Έλž˜ν‚€κ°€ λ‹€λ₯Έ ν…Œμ΄λΈ”μ— μžˆμœΌλ―€λ‘œ 연관관계 관리λ₯Ό μœ„ν•΄ μΆ”κ°€ μ—…λ°μ΄νŠΈ 쿼리 λ°œμƒ

  • μΌλŒ€λ‹€ μ–‘λ°©ν–₯ 연결은 κ³΅μ‹μ μœΌλ‘œ μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ” λ§€ν•‘

μΌλŒ€λ‹€ 단뱑ν–₯ 맀핑보닀 λ‹€λŒ€μΌ μ–‘λ°©ν–₯ 맀핑을 μ‚¬μš©ν•˜μž

μΌλŒ€μΌ(1:1) - @OneToOne

ex) νšŒμ›κ³Ό 개인 락컀의 관계

  • μ™Έλž˜ν‚€μ— DB μœ λ‹ˆν¬(UNI) μ œμ•½μ‘°κ±΄ ν•„μš”

  • 섀정은 λ‹€λŒ€μΌ λ§€ν•‘κ³Ό μœ μ‚¬

  • μ£Ό/λŒ€μƒ ν…Œμ΄λΈ” 쀑에 μ™Έλž˜ν‚€ 선택 κ°€λŠ₯

    • μ£Ό ν…Œμ΄λΈ” 선택

      • JPA 맀핑이 νŽΈλ¦¬ν•˜μ—¬ 객체지ν–₯ 개발자 μ„ ν˜Έ

      • μž₯점. μ£Ό ν…Œμ΄λΈ”λ§Œ μ‘°νšŒν•΄μ„œ λŒ€μƒ ν…Œμ΄λΈ” 데이터 확인 κ°€λŠ₯

      • 단점. 값이 μ—†μœΌλ©΄ μ™Έλž˜ν‚€μ— null ν—ˆμš©

    • λŒ€μƒ ν…Œμ΄λΈ” 선택

      • 전톡 DB 개발자 μ„ ν˜Έ

      • μž₯점. μ£Ό/λŒ€μƒ ν…Œμ΄λΈ”μ„ 1:1 κ΄€κ³„μ—μ„œ 1:N κ΄€κ³„λ‘œ λ³€κ²½ μ‹œ ν…Œμ΄λΈ” ꡬ쑰 μœ μ§€ κ°€λŠ₯

      • 단점. ν”„λ‘μ‹œ κΈ°λŠ₯의 ν•œκ³„λ‘œ μ§€μ—° λ‘œλ”©μœΌλ‘œ 섀정해도 항상 μ¦‰μ‹œ λ‘œλ”©

단방ν–₯

μ–‘λ°©ν–₯

λ‹€λŒ€λ‹€(N:M) - @ManyToMany

  • RDBλŠ” μ •κ·œν™”λœ ν…Œμ΄λΈ” 2개둜 λ‹€λŒ€λ‹€ 관계λ₯Ό ν‘œν˜„ν•  수 μ—†μœΌλ―€λ‘œ 쀑간 ν…Œμ΄λΈ”μ΄ ν•„μš”

  • κ°μ²΄λŠ” @ManyToMany, @JoinTable둜 λ‹€λŒ€λ‹€ 관계λ₯Ό ν‘œν˜„ν•  수 μžˆμ§€λ§Œ, 기타 데이터λ₯Ό ν¬ν•¨μ‹œν‚¬ 수 μ—†λŠ” ν•œκ³„λ‘œ μ‹€λ¬΄μ—μ„œλŠ” μ‚¬μš©ν•˜κΈ° 어렀움 (κ΄€κ³„ν˜• λ°μ΄ν„°λ² μ΄μŠ€ ν…Œμ΄λΈ”μ€ N:N 관계 섀계가 λΆˆκ°€λŠ₯ν•˜λ―€λ‘œ 엔티티와 ν…Œμ΄λΈ” 뢈일치 λ¬Έμ œλ„ λ°œμƒ)

    • μ—°κ²° ν…Œμ΄λΈ”μš© μ—”ν‹°ν‹°λ₯Ό μΆ”κ°€ν•˜λŠ” 방법 μ‚¬μš©

  • @ManyToMany -> @OneToMany, @ManyToOne 둜 ν’€μ–΄μ„œ μ‚¬μš©ν•˜μž.

Member.java

MemberProduct.java

id λŒ€μ‹  (member, product)λ₯Ό λ¬Άμ–΄μ„œ PK, FK둜 μ‚¬μš©ν•  μˆ˜λ„ μžˆμ§€λ§Œ,

ν–₯ν›„ λΉ„μ¦ˆλ‹ˆμŠ€μ μΈ 쑰건이 좔가될 경우λ₯Ό κ³ λ €ν•˜λ©΄, GeneratedValue IDλ₯Ό μ‚¬μš©ν•˜λŠ” 것이 더 μœ μ—°ν•˜κ³  개발이 μ‰¬μ›Œμ§€λŠ” μž₯점이 있음

Product.java

κ³ κΈ‰ λ§€ν•‘

상속관계 λ§€ν•‘

  • 객체의 상속 ꡬ쑰와 DB의 슈퍼/μ„œλΈŒνƒ€μž… 관계λ₯Ό λ§€ν•‘

  • DB 슈퍼/μ„œλΈŒνƒ€μž… 논리 λͺ¨λΈμ„ 물리 λͺ¨λΈλ‘œ κ΅¬ν˜„ν•˜λŠ” 방법

    • @DiscriminatorColumn(name=β€œDTYPE”) / μžμ‹ νƒ€μž… ν•„λ“œ μ‚¬μš© (default. DTYPE)

    • @DiscriminatorValue(β€œXXX”) / μžμ‹ νƒ€μž…λͺ… μˆ˜μ • μ‹œ (default. entity name)

    • @Inheritance(strategy=InheritanceType.XXX) / 상속 νƒ€μž…

쑰인 μ „λž΅ JOINED

  • κΈ°λ³Έ μ •μ„μœΌλ‘œ μ‚¬μš©

  • μž₯점

    • ν…Œμ΄λΈ” μ •κ·œν™” (μ €μž₯곡간 νš¨μœ¨ν™”)

    • μ™Έλž˜ν‚€ μ°Έμ‘° 무결성 μ œμ•½μ‘°κ±΄ ν™œμš©

  • 단점

    • 쑰회 쿼리가 λ³΅μž‘ν•΄μ§€κ³ , 쑰인을 많이 μ‚¬μš©ν•˜κ²Œ λ˜μ–΄ μ„±λŠ₯ μ €ν•˜

    • 데이터 μ €μž₯ μ‹œ INSERT Query 두 번 호좜

단일 ν…Œμ΄λΈ” μ „λž΅ SINGLE_TABLE

  • λ‹¨μˆœν•˜κ³  ν™•μž₯ κ°€λŠ₯성이 없을 경우 μ‚¬μš©

  • μž₯점

    • 쑰회 μ‹œ 쑰인이 ν•„μš” μ—†μœΌλ―€λ‘œ 일반적으둜 쑰회 μ„±λŠ₯이 λΉ λ₯΄κ³  λ‹¨μˆœ

  • 단점

    • μžμ‹ μ—”ν‹°ν‹°κ°€ λ§€ν•‘ν•œ μ»¬λŸΌμ€ λͺ¨λ‘ null ν—ˆμš©

    • 단일 ν…Œμ΄λΈ”μ— λ§Žμ€ ν•„λ“œλ₯Ό μ €μž₯ν•˜λ―€λ‘œ ν…Œμ΄λΈ”μ΄ 컀질 수 있고, 상황에 따라 쑰회 μ„±λŠ₯이 μ €ν•˜λ  수 있음

κ΅¬ν˜„ ν΄λž˜μŠ€λ§ˆλ‹€ ν…Œμ΄λΈ” μ „λž΅ TABLE_PER_CLASS

  • λΆ€λͺ¨ ν΄λž˜μŠ€λŠ” 좔상(abstract) 클래슀둜 생성

  • μœ μ§€ 보수 및 관리 μ΅œμ•…μœΌλ‘œ λΉ„μΆ”ν•˜λŠ” μ „λž΅..

  • μž₯점

    • μ„œλΈŒ νƒ€μž…μ„ λͺ…ν™•ν•˜κ²Œ κ΅¬λΆ„ν•΄μ„œ μ²˜λ¦¬ν•˜κΈ° 효과적

    • not null μ œμ•½μ‘°κ±΄ μ‚¬μš© κ°€λŠ₯

  • 단점

    • μžμ‹ ν…Œμ΄λΈ”μ„ ν•¨κ»˜ μ‘°νšŒν•  λ•Œ μ„±λŠ₯ μ €ν•˜(UNION Query)

    • μžμ‹ ν…Œμ΄λΈ”μ„ ν†΅ν•©ν•΄μ„œ 쿼리λ₯Ό μž‘μ„±ν•˜κΈ° 어렀움

.

@MappedSuperclass

  • 곡톡 λ§€ν•‘ 정보가 ν•„μš”ν•  경우 μ‚¬μš©

  • 좔상 클래슀 ꢌμž₯(직접 μƒμ„±ν•΄μ„œ μ‚¬μš©ν•  일이 μ—†μŒ)

  • ex. 등둝일, μˆ˜μ •μΌ, λ“±λ‘μž, μˆ˜μ •μž λ“±..

  • ν—·κ°ˆλ¦¬μ§€ μ•ŠκΈ°!

    • 상속관계 λ§€ν•‘X - μžμ‹ ν΄λž˜μŠ€μ— λ§€ν•‘ μ •λ³΄λ§Œ 제곡)

    • μ—”ν‹°ν‹°/ν…Œμ΄λΈ” λ§€ν•‘X - 쑰회, 검색(em.find(BaseEntity)) λΆˆκ°€

ν”„λ‘μ‹œ & 연관관계 관리

ν”„λ‘μ‹œ

DB 쑰회λ₯Ό λ―Έλ£¨λŠ”(Lazy) κ°€μ§œ(Proxy) μ—”ν‹°ν‹° 객체 쑰회

em.getReference()

  • μ‹€μ œ 클래슀λ₯Ό 상속 λ°›μ•„ λ§Œλ“€μ–΄μ§€κ³ , μ‹€μ œμ™€ 겉 λͺ¨μ–‘λ§Œ 같은 빈 깑톡

  • μ‹€μ œ μ—”ν‹°ν‹°μ˜ μ°Έμ‘°(target)λ₯Ό λ³΄κ΄€ν•˜κ³ , ν”„λ‘μ‹œ λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜λ©΄ μ‹€μ œ μ—”ν‹°ν‹° λ©”μ„œλ“œλ₯Ό 호좜

ν”„λ‘μ‹œ 객체 νŠΉμ§•

  • ν”„λ‘μ‹œ κ°μ²΄λŠ” 처음 μ‚¬μš©ν•  λ•Œ ν•œ 번만 μ΄ˆκΈ°ν™”

    • μ΄ˆκΈ°ν™” μ‹œ ν”„λ‘μ‹œ 객체λ₯Ό 톡해 μ‹€μ œ 엔티티에 μ ‘κ·Ό κ°€λŠ₯

  • ν”„λ‘μ‹œ κ°μ²΄λŠ” 원본 μ—”ν‹°ν‹°λ₯Ό μƒμ†λ°›μœΌλ―€λ‘œ, νƒ€μž… 체크 μ‹œ instance of μ‚¬μš©

  • ν•œ μ˜μ†μ„± μ»¨ν…μŠ€νŠΈ μ•ˆμ—μ„œ λ™μΌν•œ ID 쑰회 μ‹œ, JPAλŠ” 항상 같은 νƒ€μž…μ˜ μ—”ν‹°ν‹°λ₯Ό λ°˜ν™˜

    • μ˜μ†μ„± μ»¨ν…μŠ€νŠΈμ— μ°ΎλŠ” μ—”ν‹°ν‹°κ°€ 이미 μžˆλ‹€λ©΄, em.getReference()λ₯Ό ν˜ΈμΆœν•΄λ„ μ‹€μ œ μ—”ν‹°ν‹°λ₯Ό λ°˜ν™˜

    • λ°˜λŒ€λ‘œ ν”„λ‘μ‹œ 쑰회 ν›„, μ—”ν‹°ν‹° 쑰회λ₯Ό 해도 μ‹€μ œ μ—”ν‹°ν‹°κ°€ μ•„λ‹Œ porxy λ°˜ν™˜

  • μ€€μ˜μ† μƒνƒœμΌ λ•Œ(em.clear() / em.close() / em.detach()), ν”„λ‘μ‹œλ₯Ό μ΄ˆκΈ°ν™”ν•˜λ©΄ LazyInitializationException λ°œμƒ

μ¦‰μ‹œ λ‘œλ”©κ³Ό μ§€μ—° λ‘œλ”©

μ¦‰μ‹œ λ‘œλ”©

  • μ—°κ΄€ 객체λ₯Ό 쑰인으둜 ν•¨κ»˜ 쑰회

μ§€μ—° λ‘œλ”©

  • μ—°κ΄€ 객체λ₯Ό ν”„λ‘μ‹œλ‘œ 쑰회

  • ν”„λ‘μ‹œ λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜λŠ” μ‹œμ μ— μ΄ˆκΈ°ν™”(쑰히)

μ¦‰μ‹œ/μ§€μ—° λ‘œλ”© 주의 사항

  • μ‹€λ¬΄μ—μ„œλŠ” μ§€μ—° λ‘œλ”©λ§Œ μ‚¬μš©ν•˜μž

    • μ¦‰μ‹œ λ‘œλ”© 적용 μ‹œ, μ—°κ΄€ 관계가 λ§Žμ•„μ§€κ²Œ 되면 μ˜ˆμƒν•˜μ§€ λͺ»ν•œ SQL λ°œμƒ

    • λ˜ν•œ, JPQLμ—μ„œ N+1 문제 λ°œμƒ

  • N+1 문제 해결은 JPQL fetch join ν˜Ήμ€ Entity Graph κΈ°λŠ₯을 μ‚¬μš©ν•˜μž.

  • @ManyToOne, @OneToOne의 defaultλŠ” μ¦‰μ‹œ λ‘œλ”©μ΄λ―€λ‘œ LAZY μ„€μ • ν•„μš”

    • @OneToMany, @ManyToMany default : μ§€μ—° λ‘œλ”©

μ˜μ†μ„± 전이

CASCADE

  • νŠΉμ • μ—”ν‹°ν‹°λ₯Ό μ˜μ† μƒνƒœλ‘œ λ§Œλ“€ λ•Œ, μ—°κ΄€λœ 엔티티도 ν•¨κ»˜ μ˜μ† μƒνƒœλ‘œ λ§Œλ“€κ³  싢을 경우 μ‚¬μš©

    • 연관관계λ₯Ό λ§€ν•‘ν•˜λŠ” κ²ƒκ³ΌλŠ” 아무 κ΄€λ ¨ μ—†μŒ.

  • μ—”ν‹°ν‹°μ˜ μ†Œμœ μžκ°€ ν•˜λ‚˜μΌ λ•Œ(단일 엔티티에 쒅속적, 라이프 사이클이 μœ μ‚¬)만 μ‚¬μš©ν•˜κΈ°.

    • μ—¬λŸ¬ μ—”ν‹°ν‹°μ—μ„œ κ΄€λ¦¬λ˜λŠ” 경우 μ‚¬μš© X! (관리가 νž˜λ“€μ–΄μ§„λ‹€..)

  • μ’…λ₯˜ (보톡 ALL, PERSIST, REMOVE μ•ˆμ—μ„œ μ‚¬μš©ν•˜λ©° 라이프 사이클을 λ™μΌν•˜κ²Œ μœ μ§€)

    • ALL: λͺ¨λ‘ 적용

    • PERSIST: μ˜μ†

    • REMOVE: μ‚­μ œ

    • MERGE: 병합

    • REFRESH: REFRESH

    • DETACH: DETACH

κ³ μ•„ 객체

  • λΆ€λͺ¨ 엔티티와 연관관계가 λŠμ–΄μ§„ μžμ‹ μ—”ν‹°ν‹°

  • μ°Έμ‘°κ°€ 제거된 μ—”ν‹°ν‹°λŠ” λ‹€λ₯Έ κ³³μ—μ„œ μ°Έμ‘°ν•˜μ§€ μ•ŠλŠ” κ³ μ•„ 객체둜 보고 μ‚­μ œ

    • κ³ μ•„ 객체 제거 μ„€μ • : orphanRemoval = true

    • μ˜μ†μ„± 전이와 λ™μΌν•˜κ²Œ νŠΉμ • μ—”ν‹°ν‹°κ°€ 개인 μ†Œμœ ν•  λ•Œλ§Œ μ‚¬μš©ν•˜κΈ°

    • @OneToOne, @OneToMany만 μ‚¬μš© κ°€λŠ₯

    • λΆ€λͺ¨ μ—”ν‹°ν‹°λ₯Ό μ œκ±°ν•  λ•Œ CascadeType.REMOVE와 λ™μΌν•˜κ²Œ μžμ‹λ„ ν•¨κ»˜ 제거

  • μ˜μ†μ„± 전이와 ν•¨κ»˜ μ‚¬μš©ν•  경우 (CascadeType.ALL + orphanRemovel=true)

    • λΆ€λͺ¨ μ—”ν‹°ν‹°λ₯Ό 톡해 μžμ‹μ˜ 생λͺ… μ£ΌκΈ° 관리 κ°€λŠ₯

    • DDD Aggregate Root κ°œλ…μ„ κ΅¬ν˜„ν•  λ•Œ 유용

JPA Data Type

μ—”ν‹°ν‹° νƒ€μž…

  • @Entity둜 μ •μ˜ν•˜λŠ” 객체

  • 데이터가 변해도 μ‹λ³„μžλ‘œ 좔적 κ°€λŠ₯

κ°’ νƒ€μž…

  • μ‹λ³„μžκ°€ μ—†μœΌλ―€λ‘œ κ°’ λ³€κ²½ μ‹œ 좔적 λΆˆκ°€

  • 생λͺ… μ£ΌκΈ°λ₯Ό 엔티티에 의쑴

  • 데이터 곡유 X!

  • κΈ°λ³Έκ°’ νƒ€μž…

    • Java Basic Type : int, double..

    • Wrapper Class : Integer, Long..

    • String

  • μž„λ² λ””λ“œ νƒ€μž…

  • μ»¬λ ‰μ…˜ κ°’ νƒ€μž…

  • μ•ˆμ „ν•˜κ²Œ λΆˆλ³€ 객체둜 λ§Œλ“€κΈ°

Embedded Type

  • μƒˆλ‘œμš΄ κ°’ νƒ€μž… μ •μ˜ (κΈ°λ³Έ κ°’ νƒ€μž…μ„ λͺ¨μ•„μ„œ λ§Œλ“  볡합 κ°’ νƒ€μž…)

    • @Embeddable: κ°’ νƒ€μž… μ •μ˜

    • @Embedded: κ°’ νƒ€μž… μ‚¬μš©

μž₯점

  • κ°’ νƒ€μž…μ„ 객체지ν–₯적으둜 μ‚¬μš© (μž¬μ‚¬μš©, 높은 응집도 ..)

  • μž„λ² λ””λ“œ νƒ€μž… 클래슀만이 μ‚¬μš©ν•˜λŠ” μœ μš©ν•œ λ©”μ„œλ“œ 생성

  • μž„λ² λ””λ“œ νƒ€μž…μ„ μ†Œμœ ν•œ μ—”ν‹°ν‹°μ˜ 생λͺ…μ£ΌκΈ°λ₯Ό 의쑴

νŠΉμ§•

  • 잘 μ„€κ³„λœ ORM Application은 λ§€ν•‘ν•œ ν…Œμ΄λΈ” μˆ˜λ³΄λ‹€ 클래슀 μˆ˜κ°€ 더 많음

  • ν•œ μ—”ν‹°ν‹°μ—μ„œ 같은 μž„λ² λ””λ“œ νƒ€μž…μ„ μ‚¬μš©ν•˜μ—¬ 컬럼λͺ…이 쀑볡될 경우

    • @AttributeOverrides, @AttributeOverride λ₯Ό μ‚¬μš©ν•΄μ„œ 컬러λͺ… 속성 μž¬μ •μ˜

  • μž„λ² λ””λ“œ νƒ€μž…μ˜ 값이 null이면, λ§€ν•‘ 컬럼 κ°’ λͺ¨λ‘ null

κ°’ νƒ€μž…

λΆˆλ³€ 객체

  • κ°’ νƒ€μž…μ„ μ—¬λŸ¬ μ—”ν‹°ν‹°μ—μ„œ κ³΅μœ ν•˜λ©΄ Side Effect(λΆ€μž‘μš©) λ°œμƒ

    • μΈμŠ€ν„΄μŠ€ 값을 κ³΅μœ ν•˜λŠ” 것은 μœ„ν—˜ν•˜λ―€λ‘œ 값을 λ³΅μ‚¬ν•΄μ„œ μ‚¬μš©ν•˜κΈ°

  • κ°’ νƒ€μž…μ„ λΆˆλ³€ 객체둜 μ„€κ³„ν•˜μ—¬ 객체 νƒ€μž…μ„ μˆ˜μ •ν•  수 μ—†κ²Œ λ§Œλ“€κΈ°

    • λΆˆλ³€ 객체: 생성 μ‹œμ λ₯Ό μ œμ™Έν•˜κ³  값을 λ³€κ²½ν•  수 μ—†λŠ” 객체

      • μƒμ„±μžλ‘œλ§Œ 값을 μ„€μ •ν•˜κ³ , SetterλŠ” μƒμ„±ν•˜μ§€ μ•ŠκΈ°

      • Integer, String은 μžλ°”κ°€ μ œκ³΅ν•˜λŠ” λŒ€ν‘œμ μΈ λΆˆλ³€ 객체

κ°’ νƒ€μž… 비ꡐ

  • κ°’ νƒ€μž… λΉ„κ΅λŠ” equalsλ₯Ό μ‚¬μš©ν•œ 동등성 비ꡐλ₯Ό μ‚¬μš©

    • 동일성(identity) 비ꡐ: μΈμŠ€ν„΄μŠ€ μ°Έμ‘° κ°’ 비ꡐ ==

    • 동등성(equivalence) 비ꡐ: μΈμŠ€ν„΄μŠ€ κ°’ 비ꡐ equals()

  • κ°’ νƒ€μž…μ˜ equals() λ©”μ†Œλ“œλ₯Ό μ μ ˆν•˜κ²Œ μž¬μ •μ˜

    • ν”„λ‘μ‹œ μ‚¬μš©μ„ κ³ λ €ν•˜μ—¬ getter() μ‚¬μš© μΆ”μ²œ

κ°’ νƒ€μž… μ»¬λ ‰μ…˜

  • κ°’ νƒ€μž…μ„ ν•˜λ‚˜ 이상 μ €μž₯ν•  경우 μ‚¬μš©

    • μ…€λ ‰νŠΈ λ°•μŠ€μ™€ 같이 κ°’ 변경이 ν•„μš” μ—†λŠ” λ‹¨μˆœν•œ 경우 μ‚¬μš©

    • @ElementCollection, @CollectionTable

  • λ°μ΄ν„°λ² μ΄μŠ€λŠ” μ»¬λ ‰μ…˜μ„ 같은 ν…Œμ΄λΈ”μ— μ €μž₯ν•  수 μ—†μœΌλ―€λ‘œ, λ³„λ„μ˜ ν…Œμ΄λΈ”μ΄ ν•„μš”

    • κ°’ νƒ€μž… μ»¬λ ‰μ…˜μ€ 엔티티와 생λͺ…μ£ΌκΈ°κ°€ κ°™μŒ (Casecade.ALL + orphanRemoval=true)

  • μ €μž₯

  • 쑰회

    • default. FetchType.LAZY μ „λž΅ μ‚¬μš©

  • μˆ˜μ •

κ°’ νƒ€μž… μ»¬λ ‰μ…˜μ˜ μ œμ•½

  • κ°’ νƒ€μž… μ»¬λ ‰μ…˜μ€ 엔티티와 λ‹€λ₯΄κ²Œ μ‹λ³„μž κ°œλ…μ΄ μ—†μœΌλ―€λ‘œ λ³€κ²½ μ‹œ 좔적이 μ–΄λ €μš΄ 큰 단점 쑴재

    • λ³€κ²½ 사항이 λ°œμƒν•˜λ©΄, 주인 엔티티와 μ—°κ΄€λœ λͺ¨λ“  데이터λ₯Ό μ‚­μ œν•˜κ³ , κ°’ νƒ€μž… μ»¬λ ‰μ…˜μ— μžˆλŠ” λͺ¨λ“  값을 λ‹€μ‹œ μ €μž₯ν•˜λŠ” λΉ„νš¨μœ¨μ μΈ λ™μž‘(μ‹λ³„μžκ°€ μ—†μœΌλ―€λ‘œ..)

    • κ°’ νƒ€μž… μ»¬λ ‰μ…˜μ„ λ§€ν•‘ν•˜λŠ” ν…Œμ΄λΈ”μ€ λͺ¨λ“  μ»¬λŸΌμ„ λ¬Άμ–΄μ„œ κΈ°λ³Έ ν‚€λ‘œ ꡬ성해야 함

  • 결둠적으둜, μ…€λ ‰νŠΈ λ°•μŠ€μ™€ 같이 변경이 ν•„μš” μ—†λŠ” λ‹¨μˆœν•œ κ²½μš°κ°€ μ•„λ‹ˆλΌλ©΄, κ°’ νƒ€μž… μ»¬λ ‰μ…˜ λŒ€μ‹  μΌλŒ€λ‹€ 단방ν–₯ 관계λ₯Ό μΆ”μ²œ (μ‹λ³„μž, 지속적인 κ°’ 좔적, 변경이 ν•„μš”ν•œ 경우)

객체지ν–₯ 쿼리 μ–Έμ–΄

JPQL (Java Persistence Query Language)

  • SQL을 μΆ”μƒν™”ν•œ 객체 μ§€ν–₯ 쿼리 μ–Έμ–΄(νŠΉμ • λ°μ΄ν„°λ² μ΄μŠ€μ— 의쑴 X)

  • ν…Œμ΄λΈ”μ΄ μ•„λ‹Œ μ—”ν‹°ν‹° 객체λ₯Ό λŒ€μƒμœΌλ‘œ 쿼리

  • 문자둜 JPQL이 μž‘μ„±λ˜λ‹€λ³΄λ‹ˆ 동적 쿼리 μž‘μ„±μ΄ μ–΄λ €μš΄ 단점

QueryDSL

  • λ¬Έμžκ°€ μ•„λ‹Œ μžλ°”μ½”λ“œλ‘œ JPQL μž‘μ„±

    • 컴파일 μ‹œμ μ— 문법 였λ₯˜ 체크s

    • νŽΈλ¦¬ν•œ 동적쿼리 μž‘μ„±

  • JPQL λΉŒλ” μ—­ν• 

Reference documentationarrow-up-right

λ„€μ΄ν‹°λΈŒ SQL

  • JPQL둜 ν•΄κ²°ν•  수 μ—†λŠ” νŠΉμ • λ°μ΄ν„°λ² μ΄μŠ€μ— 의쑴적인 κΈ°λŠ₯ μ‚¬μš© μ‹œ SQL을 직접 μž‘μ„±

기타

  • JPAλ₯Ό μ‚¬μš©ν•˜λ©΄μ„œ JDBC API, SpringJdbcTemplate, MyBatis 등을 ν•¨κ»˜ μ‚¬μš© κ°€λŠ₯

  • 단, μ˜μ†μ„± μ»¨ν…μŠ€νŠΈλ₯Ό μ μ ˆν•œ μ‹œμ (SQL을 μ‹€ν–‰ν•˜κΈ° 직전)에 κ°•μ œ ν”ŒλŸ¬μ‹œ ν•„μš” (em.flush())

κΈ°λ³Έ 문법

λ°˜ν™˜ νƒ€μž…

  • TypeQuery: λ°˜ν™˜ νƒ€μž…μ΄ λͺ…ν™•ν•  λ•Œ μ‚¬μš©

  • Query: λ°˜ν™˜ νƒ€μž…μ΄ λͺ…ν™•ν•˜μ§€ μ•Šμ„ λ•Œ μ‚¬μš©

쑰회

  • query.getResultList(): κ²°κ³Όκ°€ ν•˜λ‚˜ 이상일 경우 (리슀트 λ°˜ν™˜)

    • κ²°κ³Όκ°€ μ—†μœΌλ©΄ 빈 리슀트 λ°˜ν™˜

  • query.getSingleResult(): κ²°κ³Όκ°€ μ •ν™•νžˆ ν•˜λ‚˜μΌ 경우 (단일 객체 λ°˜ν™˜)

    • κ²°κ³Όκ°€ μ—†μœΌλ©΄: javax.persistence.NoResultException

    • λ‘˜ 이상이면: javax.persistence.NonUniqueResultException

νŒŒλΌλ―Έν„° 바인딩

ν”„λ‘œμ μ…˜

  • SELECT μ ˆμ— μ‘°νšŒν•  λŒ€μƒμ„ μ§€μ •ν•˜λŠ” 방식

    • μ—”ν‹°ν‹° ν”„λ‘œμ μ…˜, μž„λ² λ””λ“œ νƒ€μž… ν”„λ‘œμ μ…˜, 슀칼라 νƒ€μž… ν”„λ‘œμ μ…˜

    • 슀칼라 νƒ€μž… ν”„λ‘œμ μ…˜μ˜ 경우 μ—¬λŸ¬ κ°’ 쑰회 μ‹œ DTO 쑰회 μΆ”μ²œ

νŽ˜μ΄μ§•

  • setFirstResult(int startPosition) : 쑰회 μ‹œμž‘ μœ„μΉ˜

  • setMaxResults(int maxResult) : μ‘°νšŒν•  데이터 수

쑰인

  • λ‚΄λΆ€ 쑰인:

    • 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

.

  • Join On (JPA 2.1, Hibernate 5.1 이상)

    • 쑰인 λŒ€μƒ 필터링

      • SELECT m, t FROM Member m LEFT JOIN m.team t on t.name = 'A'

    • 연관관계가 μ—†λŠ” μ—”ν‹°ν‹° μ™ΈλΆ€ 쑰인

      • SELECT m, t FROM Member m LEFT JOIN Team t on m.username = t.name

μ„œλΈŒ 쿼리

  • 지원 ν•¨μˆ˜

    • [NOT] EXISTS (Subquery): μ„œλΈŒμΏΌλ¦¬μ— κ²°κ³Όκ°€ μ‘΄μž¬ν•˜λ©΄ μ°Έ

    • {ALL | ANY | SOME} (Subquery)

      • ALL: λͺ¨λ‘ λ§Œμ‘±ν•˜λ©΄ μ°Έ

      • ANY, SOME: 쑰건을 ν•˜λ‚˜λΌλ„ λ§Œμ‘±ν•˜λ©΄ μ°Έ

    • [NOT] IN (Subquery): μ„œλΈŒμΏΌλ¦¬μ˜ κ²°κ³Ό 쀑 ν•˜λ‚˜λΌλ„ 같은 것이 있으면 μ°Έ

.

  • ν•œκ³„

    • JPAλŠ” WHERE, HAVING μ ˆμ—μ„œλ§Œ μ„œλΈŒ 쿼리 μ‚¬μš© κ°€λŠ₯

      • Hibernateλ₯Ό μ‚¬μš©ν•  경우 SELECT μ ˆλ„ κ°€λŠ₯

    • FROM 절의 μ„œλΈŒ μΏΌλ¦¬λŠ” ν˜„μž¬ JPQLμ—μ„œ λΆˆκ°€λŠ₯ (쑰인으둜 풀어보기)

νƒ€μž… ν‘œν˜„

  • 문자: 'She''s'

  • 숫자: 10L(Long), 10D(Double), 10F(Float)

  • Boolean: true, false

  • ENUM: jpql.MemberType.Admin (νŒ¨ν‚€μ§€λͺ… 포함) or query.setParameter()

  • μ—”ν‹°ν‹° νƒ€μž…: 상속 κ΄€κ³„μ—μ„œ μ‚¬μš©

    • 쑰회 λŒ€μƒμ„ νŠΉμ • μžμ‹μœΌλ‘œ ν•œμ •

    • νƒ€μž… μΊμŠ€νŒ…

  • COALESCE : νŠΉμ • 컬럼이 Null일 경우 λŒ€μ²΄ κ°’ λ°˜ν™˜

  • NULLIF : μ§€μ •λœ 두 식이 κ°™μœΌλ©΄ Null λ°˜ν™˜

쀑급 문법

경둜 ν‘œν˜„μ‹

  • μƒνƒœ ν•„λ“œ (m.username): 경둜 νƒμƒ‰μ˜ 쒅점 (탐색 λΆˆκ°€)

  • 단일 κ°’ μ—°κ΄€ 경둜 (m.team): λ¬΅μ‹œμ  λ‚΄λΆ€ 쑰인(inner join) λ°œμƒ (탐색 κ°€λŠ₯)

  • μ»¬λ ‰μ…˜ κ°’ μ—°κ΄€ 경둜 (m.orders): λ¬΅μ‹œμ  λ‚΄λΆ€ 쑰인 λ°œμƒ (탐색 λΆˆκ°€)

    • λͺ…μ‹œμ  쑰인을 톡해 λ³„μΉ­μœΌλ‘œ 탐색 κ°€λŠ₯

.

  • λͺ…μ‹œμ  쑰인: JOIN ν‚€μ›Œλ“œλ₯Ό 직접 μ‚¬μš©

    • 쑰인이 λ°œμƒν•˜λŠ” 상황을 ν•œ λˆˆμ— νŒŒμ•…ν•  수 μžˆμ–΄μ„œ 쿼리 νŠœλ‹μ΄ 편리

    • 쑰인은 SQL νŠœλ‹μ— μ€‘μš”ν•œ ν¬μΈνŠΈμ΄λ―€λ‘œ, 가급적 λͺ…μ‹œμ  쑰인을 μ‚¬μš©ν•˜μž !!

  • λ¬΅μ‹œμ  쑰인: 경둜 ν‘œν˜„μ‹μ— μ˜ν•΄ λ¬΅μ‹œμ μœΌλ‘œ 쑰인 λ°œμƒ

    • λ‚΄λΆ€ 쑰인만 κ°€λŠ₯

    • 쑰인 쿼리λ₯Ό νŒŒμ•…ν•˜κΈ° 어렀움

μ—”ν‹°ν‹° 직접 μ‚¬μš©

  • JPQLμ—μ„œ μ—”ν‹°ν‹°λ₯Ό 직접 μ‚¬μš©ν•˜λ©΄ SQLμ—μ„œ ν•΄λ‹Ή μ—”ν‹°ν‹°μ˜ κΈ°λ³Έ ν‚€ 값을 μ‚¬μš©

Named Query

  • 미리 μ •μ˜ν•΄λ‘κ³  μ‚¬μš©ν•˜λŠ” JPQL 정적 쿼리

  • μ• ν”Œλ¦¬μΌ€μ΄μ…˜ λ‘œλ”© μ‹œμ μ— 쿼리 검증 및 캐싱 ν›„ μž¬μ‚¬μš©

벌크 μ—°μ‚°

  • ν•œ 번의 쿼리둜 μ—¬λŸ¬ μ—”ν‹°ν‹° λ³€κ²½ (UPDATE, DELETE)

    • executeUpdate()둜 영ν–₯을 받은 μ—”ν‹°ν‹° 수 확인 κ°€λŠ₯

  • 벌크 연산은 μ˜μ†μ„± μ»¨ν…μŠ€νŠΈλ₯Ό λ¬΄μ‹œν•˜κ³  λ°μ΄ν„°λ² μ΄μŠ€μ— 직접 쿼리λ₯Ό μ „λ‹¬ν•˜λ―€λ‘œ

    • 벌크 연산을 λ¨Όμ € μ‹€ν–‰ν•˜κ±°λ‚˜

    • 벌크 μ—°μ‚° μˆ˜ν–‰ ν›„ μ˜μ†μ„± μ»¨ν…μŠ€νŠΈ μ΄ˆκΈ°ν™” (em.clear())

페치 쑰인

Fetch Join

  • JPQL μ„±λŠ₯ μ΅œμ ν™”λ₯Ό μœ„ν•΄ 제곡

  • 쿼리 ν•œ λ²ˆμ— μ—°κ΄€λœ μ—”ν‹°ν‹°λ‚˜ μ»¬λ ‰μ…˜μ„ ν•¨κ»˜ 쑰회 (μ¦‰μ‹œ λ‘œλ”© μš°μ„  적용)

    • 일반 μ‘°μΈμ—μ„œλŠ” μ—°κ΄€λœ μ—”ν‹°ν‹°λ₯Ό ν•¨κ»˜ μ‘°νšŒν•˜μ§€ μ•ŠμŒ

  • N + 1 이슈의 ν•΄κ²° 방법

  • [ LEFT [OUTER] / INNER ] JOIN FETCH

Collection Fetch Join

  • μΌλŒ€λ‹€ κ΄€κ³„μ—μ„œμ˜ 페치 쑰인

  • μΌλŒ€λ‹€ κ΄€κ³„μ—μ„œμ˜ N+1 λ¬Έμ œλŠ” batchSize μ„€μ •μœΌλ‘œ ν•΄κ²° κ°€λŠ₯

    • LAZY λ™μž‘ μ‹œ, IN 쿼리둜 size 만큼 ν•œ λ²ˆμ— 쑰회

      • κ°œλ³„ μ„±μ •

      • Global μ„€μ •

    • SQL

DISTINCT

  • JPQLμ—μ„œ DISTINCTκ°€ μ œκ³΅ν•˜λŠ” κΈ°λŠ₯

    • 쿼리에 DISTINCT μΆ”κ°€

    • μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ—μ„œ 쀑볡 μ—”ν‹°ν‹° 제거

ν•œκ³„

  • 페치 쑰인 λŒ€μƒμ—λŠ” 별칭 λΆˆκ°€

    • 객체 κ·Έλž˜ν”„ 사상(N에 ν•΄λ‹Ήν•˜λŠ” λͺ¨λ“  데이터 쑰회λ₯Ό κΈ°λŒ€)κ³Ό λ§žμ§€ μ•ŠμŒ

    • t.membersμ—μ„œ 쑰건을 κ±Έκ³  μ‹Άλ‹€λ©΄, memberλ₯Ό selectμ ˆμ—μ„œ μ‚¬μš©ν•˜μž.

  • μ»¬λ ‰μ…˜μ€ ν•œ 개만 페치 쑰인 κ°€λŠ₯

  • μ»¬λ ‰μ…˜ 페치 쑰인을 ν•˜λ©΄ νŽ˜μ΄μ§• API μ‚¬μš© λΆˆκ°€

    • 단일 κ°’ μ—°κ΄€ ν•„λ“œ(1:1/N:1)λŠ” 페치 쑰인을 해도 νŽ˜μ΄μ§• κ°€λŠ₯

    • μ»¬λ ‰μ…˜ 페치 쑰인으둜 μ»¬λ ‰μ…˜ 데이터가 μž˜λ¦¬λŠ” ν˜„μƒ λ°œμƒ

Last updated