- EntityManager
- JPA (Java Persistence API)에서 제공하는 핵심 인터페이스
- 엔티티 객체와 데이터베이스 간의 상호작용을 관리
- 주요 기능으로는 엔티티의 생성, 조회, 업데이트, 삭제
- JPA의 영속성 컨텍스트(persistence context)
- JPA에서는 EntityManager를 통해 엔티티 객체를 관리
- EntityManager는 영속성 컨텍스트라는 세션과 같은 캐시를 유지하며, 이 컨텍스트 내의 엔티티는 관리 상태(persisted state)
- 관리 상태에 있는 엔티티에 대한 변경 사항은 자동으로 데이터베이스에 반영
- 변경 감지(dirty checking) 메커니즘
- 더티체킹이라고 불리기도 하는 메커니즘
- JPA는 트랜잭션이 커밋될 때 영속성 컨텍스트 내의 엔티티를 스캔하여 변경된 엔티티 검색
- 변경된 엔티티가 감지되면, JPA는 save가 없어도 해당 변경 사항을 데이터베이스에 자동으로 반영
- SpingDataJpa 메서드 명명규칙
- findBy<Property>
- 특정 필드의 값으로 엔티티를 검색. where propety = ?
- findByNameAndEmail(String name, String email)
- findByNameOrEmail(String name, String email)
- findBy<Property>Between
- 두 값 사이의 범위로 조회
- findByAgeBetween(int start, int end)
- findBy<Property>LessThan
- 주어진 값보다 작은 값을 가진 엔티티를 조회
- findByAgeLessThan(int age)
- findBy<Property>GreaterThan
- findBy<Property>IsNull 또는 findBy<Property>IsNotNull
- findBy<Property>OrderBy<Property>Asc/Desc
- 전체조회시 orderBy
- 특정 필드에 대한 정렬 기준을 지정
- Page<Entitiy> findBy<Property>(<PropertyType> value, Pageable pageable)는 페이징 처리를 위한 메서드
- JPQL문
- jpa의 객체지향 쿼리문법
- 장점
- DB에 따라 문법이 달라지 않는 객체지향언어, spring data jpa에서 사용시 컴파일타임에서도 jpql의 문법 check하고 검증
- 단점
- DB고유의 기능과 성능을 극대화하기는 어려움.
- SELECT
- 기본 형태: SELECT <projection> FROM <entity> [WHERE <condition>]
- SELECT m FROM Member m WHERE m.age > 18
- 엔티티의 특정 필드만 선택하려면, SELECT m.name, m.age FROM Member m 와 같이 사용
- JOIN
- SELECT m FROM Member m JOIN m.team
- SELECT m FROM Member m LEFT JOIN m.team t
- JPA의 Entity 관련 주요 설정정보
- @OneToMany
- OneToMany어노테이션은 일대다 관계를 의미
- mappedBy: 양방향 관계에서, 연관 관계의 주인을 지정.
- 연관 관계의 주인이란 JPA에서 관계를 맺고 있는 두 엔티티 중 관계를 관리(데이터베이스의 외래 키를 업데이트)하는 책임을 가지는 쪽을 의미
- "many" 쪽 엔티티의 필드 이름을 값으로 설정
- 연관 관계의 주인이 Many쪽임에 유의
- cascade
- 엔티티 상태 변화(예: 저장, 삭제)를 연관된 엔티티에 전파하는 방식을 지정
- 부모 엔티티를 삭제할 때 CascadeType.REMOVE 또는 CascadeType.ALL이 설정된 자식 엔티티도 함께 삭제
- 예를 들어 author객체에 posts객체를 set하여 author객체를 save할 경우 cascade옵션이 설정돼 있으면 post객체에도 save
- Cascade를 사용하면, 부모 엔티티를 저장할 때 자동으로 연관된 자식 엔티티들도 함께 저장함으로서 코드를 간결하게 만들고, 엔티티 간의 관계를 명확하게 표현
- 더티체킹과 비교하면 더티체킹은 변경사항에 대해서만 반영하지만 cascade옵션을 통해서는 연관엔티티의 신규 사항 추가 가능
- fetch
- "fetch"는 가져오다라는 의미를 가진 단어로서, 엔티티 또는 엔티티의 연관된 컬렉션 및 엔티티를 데이터베이스로부터 어떻게 로드할지 결정하는 전략
- FetchType.LAZY는 지연 로딩, FetchType.EAGER는 즉시 로딩
- lazy설정시 엔티티를 참조하지 않는한 자식테이블로 쿼리발생X
- 참조할 경우에는 N+1이슈가 발생하나, 참조하지 않으면 N+1이슈 발생안함
- eager설정시 즉시, 상대엔티티를 참조하지 않더라도 자식테이블로 쿼리발생O
- @OneToMany과 OneToOne은 default설정이 FetchType.LAZY. @ManyToOne은 default가 FetchType.EAGER
- @ManyToOne
- @JoinColumn
- 외래 키 명을 지정할때 사용
- name 속성으로 외래 키 컬럼의 이름을 지정
- nullable 속성으로 nullable 또는 not null지정
- fetch와 N+1문제
- JPA의 기본사상은, 연관관계에 있는 테이블의 데이터를 먼저 JOIN을 통해 데이터를 한꺼번에 가져 오는 것이 아닌, 추후에 연관 엔티티 참조시에 연관데이터를 조회하는 전략을 취함
- 이때에 조회하는 방식으로 인해 N+1 문제 발생
- 예시) 자식 엔티티를 조회하면, 자식 엔티티를 로드하는 1번의 쿼리와 부모엔티티(10개가 있다고 가정) 로드를 위한 10번의 쿼리가 발생하여 총 11번의 쿼리 발생
- 다수의 쿼리로 인한 성능이슈 해결책으로 jpql의 fetch join 사용
- fetch join을 통해 연관엔티티를 한꺼번에 가져옴으로서 N+1을 방지
- 일반 JOIN과의 차이점은 일반 JOIN은 연관된 엔티티(Post 객체 등)를 실제로 로드하지 않는 다는 것
- 이로 인해 일반 join을 하더라도 select * from post;와 실질적으로 차이가 없는 N+1발생 가능성 존재 다만 아래와 같은 목적으로 사용 가능
- 일반 JOIN을 사용한 조건부 검색
- select p from Post p left join p.author
- fetch JOIN을 사용한 성능 최적화
- select p from Post p left join fetch p.author