점점 강해지고 있습니다.
[Spring] JPA 공부
JPA는 표준 ORM(Object-Relational Mapping)으로 Hibernate라는 ORM 프레임워크를 사용해서 구현한다.
EntityManagerFactory 는 리소스를 많이 사용하기 때문에 하나만 생성에서 애플리케이션 내부에서 전체 공유해서 사용
EntityManager은 한번 쓰고 버려야 함. 여러 쓰레드에서 공유하면 안된다.
JPA의 모든 데이터 변경은 트랜잭션 안에서 실행
JPQL
- SQL를 추상화한 객체지향 버전
JPQL : 엔티티 객체를 대상으로 쿼리
SQL : 데이터베이스 대상으로 쿼리
영속성 컨텍스트
JPA를 이해하는 데 가장 중요한 용어
엔티티를 영구 저장하는 환경
영속성 컨텍스트는 논리적인 개념
엔티티 매니저를 통해 영속성 컨텍스트에 접근
엔티티의 생명주기
- 비영속(new/transient)
영속성 컨텍스트와 전혀 관계가 없는 새로운 상태
- 영속(managed)
영속성 컨텍스트에 관리되는 상태
- 준영속(detached)
영속성 컨텍스트에 저장되었다가 분리된 상태
- 삭제(removed)
삭제된 상태
영속성 컨텍스트란?
Entity와 DB 사이를 연결해 주는 임시 저장 공간이라고 생각하면 쉽다.
Java – 영속성 컨텍스트(1차 캐시) – DB
데이터를 저장할 때 영속성 컨텍스트에 저장되고,
` 데이터를 요청할 때 영속성 컨텍스트에 저장된다.`
이렇게 해서 여러번 쿼리를 날릴 필요 없이 필요한 쿼리만 전송할 수 있다.(1차 캐시에 해당 데이터가 있으면 그것을 사용하면 되기 때문에)
영속성 컨텍스트(1차 캐시)는 트랜잭션 내에 있으며 트랜잭션이 초기화되면 데이터가 삭제된다.
쿼리를 실행하면 1차 캐시에 저장되고, 트랜잭션이 끝날 때 쿼리가 DB로 날라가서 정보를 저장/요청 한다.
- 쓰기 지연
- 변경 감지
플러시 flush()
영속성 컨텍스트의 변경내용을 DB에 동기화하는 작업
플러시가 되는 경우
- em.flush() - 직접호출
- transaction commit - 플러시 자동 호출
- JPQL 쿼리 실행 - 플러시 자동 호출
주의점 : 영속성 컨텍스트를 비우지 않음!
준영속 상태
영속성 콘텍스트를 초기화 하는 것
영속 상태의 엔티티가 영속성 컨텍스트에서 분리
엔티티 @Entity
JPA가 관리한다
테이블과 매핑할 클래스
주의사항
기본생성자 필수
final, enum, interface, inner 클래스 사용 X
엔티티 매핑 어노테이션
어노테이션 | 설명 |
---|---|
@Column | 컬럼 |
@Temporal | 날짜 타입 |
@Enumerated | enum 타입 |
@Lob | BLOB, CLOB 타입 매핑 |
@Transient | 특정 필드를 Table 컬럼에서 제외 |
권장하는 식별자 전략
기본 키 제약 조건: null X, 유일, 변하면 안된다.
미래까지 이 조건을 만족하는 자연키는 찾기 어려움. 대체키 사용
권장 : Long형 + 대체키 + 키 생성전략 사용(auto increment, sequence 전략 등..)
엔티티 연관관계
다중성, 방향성, 연관관계 주인 설정을 해주어야 함
테이블에서는 기본적으로 양방향 연관관계가 적용됨 (Join)
하지만, 객체에서는 단방향 연관관계임
이 상황에서 양방향으로 설정했을 경우 어떤 테이블 기준으로 데이터를 삭제하면 그것에 관련된 데이터들을 다 삭제할 것인가? 라는 물음에서 답으로 연관관계 주인 설정이 나타남
양방향 매핑 규칙
객체의 두 관계 중 하나의 연관 관계를 주인으로 지정
주인만이 외래 키 관리(등록, 수정)
주인이 아닌 쪽은 읽기만 가능
주인은 mappedby 속성 X
외래 키(FK)가 있는 곳을 주인을 설정해 준다.
'다' 쪽이 주인이다.
@ManyToOne 은 항상 주인이다.
JpaRepository
- Read : find** 로 시작
- Delete : delete** 로 시작
- Create : save
- Update : 객체 조회 후 값 변경 그리고 다시 save
Builder 패턴에서 객체 생성할 때 Tip
설계자가 객체를 생성할 떄 순서를 고려하지 않을 때를 방지, 생성자 앞에 @Builder 어노테이션을 작성.