영속성 관리 - 내부 동작 방식
영속성 컨텍스트 1
-
jpa에서 가장 중요한 2가지
- 객체와 관계형 데이터베이스 매핑하기
- 영속성 컨텍스트
-
영속성 컨텍스트
- 엔티티를 영구저장하는 환경이라는 뜻
- entityManager.persist(entity);
- 엔티티를 영속성 컨텍스트에 저장(db에 저장x)
-
엔티티의 생명주기
- 비영속: 영속성 컨텍스트와 전혀 관계가 없는 새로운 상태
- 영속: 영속성 컨텍스트에 관리되는 상태
- 준영속: 영속성 컨텍스트에 저장되었다 분리된 상태
- 삭제
💡
영속성 컨텍스트로 얻게되는 이점?

- 유저가 찾는 것이 1차 캐시에 없으면 db에서 조회를 한다
- db에서 가져온 데이터를 1차 캐시에 저장 후 1차 캐시에 있는 데이터를 반환한다
- → 영속 엔티티의 동일성 보장(==로 비교 시에도 같음 보장(동일 객체))
- 영속성 컨텍스트는 트랜잭션 단위로 생성되고 트랜잭션이 끝나면 종료된다(1차 캐시도 함께 사라진다)
- 1차 캐시가 사라질 때 비즈니스 로직이 아주 복잡한 경우 이득을 얻을 수 있는 방법도 존재한다.
💡
2차 캐시? : 어플리케이션 전체에서 공유하는 캐시

- 영속성 컨텍스트에는 쓰기 지연 sql 저장소도 있다
- 스냅샷에 1차 캐시에 들어온 상태를 떠놓고 커밋 시점에 모든 데이터를 비교 후 쓰기 지연 sql 저장소에 저장을 하고 db에 커밋을 수행한다
엔티티 매핑
객체와 테이블 매핑
- @Entity
- JPA가 관리하는 엔티티임을 표시한다
- JPA를 사용해서 테이블과 매핑할 클래스는 이 애노테이션이 필수다
자동 생성 속성
옵션 | 설명 |
---|
create | 기존테이블 삭제 후 다시 생성(DROP + CREATE) |
create-drop | create와 같으나 종료시점에 테이블 DROP |
update | 변경분만 반영(운영DB에서는 사용하면 안됨) |
validate | 엔티티와 테이블이 정상 매핑 되어 있는지만 확인 |
none | 사용하지 않음 |
💡
운영장비에는 절대 create, create-drop, update 사용하면 안된다.
필드와 컬럼 매핑
@Column
- name: 필드와 매핑할 테이블의 컬럼 이름(기본값: 객체의 필드 이름)
- length: 문자 길이 제약조건, String 타입에 사용한다.
- etc..
@Enumerated
- 자바 enum 타입을 매핑할 때 사용
- ORDINARY 사용X
- ORDINARY를 쓰면 ENUM 타입에 값이 추가될 때 기존 값이 변경이 안되므로 운영 상황에서 심각한 문제가 발생한다. → String으로 문자열을 저장하도록 한다.
속성 | 설명 | 기본값 |
---|
value | - EnumType.ORDINARY: enum 순서를 데이터베이스에 저장 | |
- EnumType.STRING: enum 이름을 데이터베이스에 저장 | EnumType.ORDINARY | |
@Temporal
- java 8부터는 최신 하이버네이트에서 지원하므로 잘 쓰지 않는다.
@Lob
- 지정할 수 있는 타입이 없다.
- CLOB: String, char[], java.sql.CLOB
- BLOB: byte [], java.sql.BLOB
@Transient
- 데이터베이스에 저장 X, 조회X
- 메모리에만 임시로 어떤 값을 보관하고 싶을 때 사용한다.
기본 키 매핑
기본 키 매핑 방법
- 직접 할당: @Id 만 사용
- 자동 생성(@GeneratedValue)
IDENTITY 전략 - 특징
- 기본 키 생성을 데이터베이스에 위임한다.
- JPA는 보통 트랜잭션 커밋 시점에 INSERT SQL 실행
- IDENTITY 전략은 DB에 저장되는 순간 PK값을 알 수 있기 때문에 필요한 시점에 em.persist로 DB에 저장해야 조회된다.
SEQUENCE 전략 - 매핑
- 주로 오라클 같은 곳에서 사용한다
- 데이터베이스 시퀀스는 유일한 값을 순서대로 생성하는 특별한 데이터베이스 오브젝트이다.
- 오라클, PostgreSQL, DB2, H2 에서 사용
단방향 연관관계
- 참조 대신에 외래키를 그대로 사용하면 안된다
- em.persist()로 영속화 하면 pk 값이 생성되고 영속된다.
객체를 테이블에 맞추어 데이터 중심으로 모델링하면, 협력 관계를 만들 수 없다.
- 테이블은 외래 키로 조인을 사용해서 연관된 테이블을 찾는다.
- 객체는 참조를 사용해서 연관된 객체를 찾는다.
- 테이블과 객체 사이에는 이런 큰 간격이 있다.
객체 지향 모델링(객체 연관관계 사용)

Team team = new Team();
team.setName("TeamA");
em.persist(team);
Member member = new Member();
member.setUsername("member1");
member.setTeam(team);
Team findTeam = findMember.getTeam();
양방향 연관관계와 연관관계의 주인 1 - 기본
누구를 주인으로?
- 외래 키가 있는 곳을 주인으로 정해라
- 이 기준으로 간단하게 JPA 사용가능
양방향 연관관계와 연관관계의 주인 2- 주의점, 정리
- Setter는 쓰지 않고 ChangeMethod를 따로 만들어서 사용한다.
양방향 연관관계 주의 - 실습
- 순수 객체 상태를 고려해서 항상 양쪽에 값을 설정하자
- 연관관계 편의 메소드를 생성하자
- 양방향 매핑시에 무한 루프를 조심하자
- 예: toString(), lombok, JSON 생성 라이브러리
실무에서 컨트롤러에서 엔티티를 반환하면 안된다.
→ 이것만 해도 많은 문제가 해결된다.
양방향 매핑 정리
- 단방향 매핑만으로도 이미 연관관계 매핑은 완료
- 양방향 매핑은 반대 방향으로 조회 기능이 추가된 것 뿐
- JPQL에서 역방향으로 탐색할 일이 많음
- 단방향 매핑을 잘 하고 양방향은 필요할 때 추가해도 됨(테이블에 영향을 주지 않음)
- 설계 입장에서 양방향은 좋을게 없다.
- 고려할게 복잡해지고 많아진다.
- 이득이 객체 입장에서 거의 없다.
💡 단방향 매핑을 잘 하고 양방향은 필요할 때 추가해도 됨(테이블에 영향을 주지 않음)
연관관계의 주인은 외래키 위치를 기준으로 정해야함
가능하면 단방향으로 해라.
비즈니스 상 설계를 잘 고려해야한다.
TABLE 전략
- Sequence 전략을 흉내내는 것
- 테이블을 하나 만들어서 키 생성 전용 테이블로 사용
- 성능이 떨어진다.
권장하는 식별자 전략
- 기본 키 제약 조건: null 아님, 유일, 변하면 안된다.
- 미래까지 이 조건을 만족하는 자연키는 찾기 어렵다. 대리키(대체키)를 사용하자.
- 예를 들어 주민등록번호도 기본 키로 적절하지 않다.
- 권장: Long형 + 대체키 + 키 생성전략 사용
상속관계 매핑
- 관계형 데이터베이스는 상속관계 X
- 슈퍼타입 서브타입 논리 모델을 실제 구현하는 방법
단일 테이블 전략

- @Inheritance(strategey=InheritanceType.SINGLE_TABLE)
- 단점
- 자식 엔티티가 매핑한 컬럼은 모두 null 허용
- 단일 테이블에 모든 것을 저장하므로 테이블이 커질 수 있어서 조회 성능이 오히려 느려질 수 있다.
구현 클래스마다 테이블 전략

- name, price를 각각의 테이블이 다 갖는 방식
- 쓰면 안되는 전략이다.
- 데이터베이스 설계자와 ORM 전문가 둘 다 비추천하는 전략이다.
조인 전략
- 장점
- 테이블 정규화
- 외래 키 참조 무결성 제약조건 활용가능
- 저장공간 효율화
- 단점
- 조회 시 조인을 많이 사용, 성능 저하
- 조회 쿼리가 복잡함
- 데이터 저장 시 INSERT sql 2번 호출
→ 조인 전략이 정석이고 객체랑도 잘 맞고 설계 입장에서 좋다.
💡 단일테이블 전략이랑 조인 전략 두가지를 트레이드 오프로 고민에 둬야한다.
→ 단순한 것에는 (데이터도 얼마 안될 때) 단일 테이블로 간다.
비즈니스적으로 중요하고 복잡하다면 조인 전략으로 간다.
Mapped Superclass - 매핑 정보 상속
@MappedSuperclass


- 속성만 상속받아 사용할 수 있다.
- 상속관계 매핑이 아님.
- 엔티티 X, 테이블과 매핑 X
- 자식 클래스에 매핑 정보만 제공
- 조회, 검색불가
- 직접 생성해서 사용할 일이 없으므로 추상 클래스 권장
- @Entity나 @MappedSuperclass로 지정한 클래스만 상속할 수 있다
상속관계 매핑
- 관계형 데이터베이스는 상속관계 X
- 슈퍼타입 서브타입 논리 모델을 실제 구현하는 방법
단일 테이블 전략

- @Inheritance(strategey=InheritanceType.SINGLE_TABLE)
- 단점
- 자식 엔티티가 매핑한 컬럼은 모두 null 허용
- 단일 테이블에 모든 것을 저장하므로 테이블이 커질 수 있어서 조회 성능이 오히려 느려질 수 있다.
구현 클래스마다 테이블 전략

- name, price를 각각의 테이블이 다 갖는 방식
- 쓰면 안되는 전략이다.
- 데이터베이스 설계자와 ORM 전문가 둘 다 비추천하는 전략이다.
조인 전략
- 장점
- 테이블 정규화
- 외래 키 참조 무결성 제약조건 활용가능
- 저장공간 효율화
- 단점
- 조회 시 조인을 많이 사용, 성능 저하
- 조회 쿼리가 복잡함
- 데이터 저장 시 INSERT sql 2번 호출
→ 조인 전략이 정석이고 객체랑도 잘 맞고 설계 입장에서 좋다.
💡 단일테이블 전략이랑 조인 전략 두가지를 트레이드 오프로 고민에 둬야한다.
→ 단순한 것에는 (데이터도 얼마 안될 때) 단일 테이블로 간다.
비즈니스적으로 중요하고 복잡하다면 조인 전략으로 간다.
Mapped Superclass - 매핑 정보 상속
@MappedSuperclass


- 속성만 상속받아 사용할 수 있다.
- 상속관계 매핑이 아님.
- 엔티티 X, 테이블과 매핑 X
- 자식 클래스에 매핑 정보만 제공
- 조회, 검색불가
- 직접 생성해서 사용할 일이 없으므로 추상 클래스 권장
- @Entity나 @MappedSuperclass로 지정한 클래스만 상속할 수 있다