| name | jpa-patterns |
| description | Use when designing JPA entities, writing JPQL/Criteria queries, resolving N+1 problems, configuring HikariCP, or choosing ID generation strategies. Do NOT use for raw SQL optimization (use sql-optimization-patterns). |
| paths | **/*.java, **/build.gradle*, **/pom.xml |
JPA/Hibernate Patterns
ํ๋ก๋์
์ด์๋ฅผ ๋ง๋๋ ์ง์ ๋ง ๋ด๋๋ค. JPA APIยท๋งคํ ๋ฌธ๋ฒ ์ง์์ ๋ชจ๋ธ์ ์ด๋ฏธ ์์.
CRITICAL Rules
- NEVER use
FetchType.EAGER on @OneToMany or @ManyToMany collections
- ALWAYS disable OSIV:
spring.jpa.open-in-view=false
- NEVER use Lombok
@Data on entities โ breaks equals/hashCode, triggers lazy loading via toString
- ALWAYS use
@Transactional(readOnly = true) for read-only service methods
- NEVER rely on
hibernate.ddl-auto in production โ use Flyway or Liquibase
- ALWAYS initialize collections:
private List<X> items = new ArrayList<>()
- Prefer
SEQUENCE (allocationSize=50) over IDENTITY when batch inserts matter
- NEVER return entities directly from controllers โ use DTO projections
- Keep transactions short โ no HTTP calls or heavy computation inside
@Transactional
- equals/hashCode: Vlad Mihalcea ํจํด โ
id != null && id.equals(other.getId()) + getClass().hashCode()
Production Properties
spring.jpa.open-in-view=false
# Batch inserts (SEQUENCE ์ ๋ต ํ์ โ IDENTITY๋ ๋ฐฐ์น ๋ถ๊ฐ)
spring.jpa.properties.hibernate.jdbc.batch_size=50
spring.jpa.properties.hibernate.order_inserts=true
spring.jpa.properties.hibernate.order_updates=true
# HikariCP: connections = (core_count x 2) + effective_spindle_count
spring.datasource.hikari.maximum-pool-size=10
Gotchas
- โ
@ManyToOne(fetch = FetchType.EAGER) โ LAZY ๊ธฐ๋ณธ, ํ์์ JOIN FETCH
- โ
equals()/hashCode()๋ฅผ Lombok/IDE ์๋ ์์ฑ์ผ๋ก โ Vlad Mihalcea ํจํด ์ฌ์ฉ
- โ JOIN FETCH๋ฅผ List ์ปฌ๋ ์
2๊ฐ ์ด์์ โ
MultipleBagFetchException. Set ์ฐํ ๋ง๊ณ ๋ณ๋ ์ฟผ๋ฆฌ๋ก ๋ถ๋ฆฌ
- โ N+1 ํด๊ฒฐ์
@EntityGraph ๋จ์ฉ โ JOIN FETCH ๋๋ DTO projection ์ฐ์
- โ bulk
@Modifying @Query ํ stale entity โ @Modifying(clearAutomatically = true)
- โ
@DataJpaTest์ H2 ์ฌ์ฉ โ Testcontainers๋ก ์ค์ DB
- โ deep pagination์ OFFSET โ keyset/cursor ํ์ด์ง๋ค์ด์
N+1 ๊ฒ์ฆ์ SQL ๋ก๊ทธ๋ก:
logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.orm.jdbc.bind=TRACE
Cross-References
| Topic | Skill |
|---|
| Raw SQL, index design, EXPLAIN | sql-optimization-patterns |
| Records/sealed types (์ํฐํฐ์ record ๊ธ์ง) | java-modern-patterns |
| Spring Boot ํ
์คํธ ์ฌ๋ผ์ด์ค | springboot-tdd |
Authoritative Sources
- Vlad Mihalcea โ vladmihalcea.com, "High-Performance Java Persistence"
- HikariCP Wiki โ github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing