들어가며
4강은 내용이 많아 1편과 2편으로 나눠 진행하였다. 엔티티 매핑 전략에 대한 내용을 정리한다.
JPA 대표 매핑 어노테이션
- 객체와 테이블 매핑 : @Entity, @Table
- 기본 키 매핑 : @Id
- 필드와 컬럼 매핑 : @Column
- 연관관계 매핑 : @ManyToOne, @JoinColumn
4.1 @Entity
- JPA를 사용를 사용하여 매핑할 클래스는 @Entity 어노테이션 필수
- 속성
- name : JPA에서 사용할 엔티티 이름 설정, 설정하지 않으면 클래스 이름 그대로 사용
- 주의사항
- 기본 생성자는 필수
- final 클래스, enum, interface, inner 클래스에는 사용 불가
- 저장할 필드에 final을 사용하면 안된다
4.2 @Table
- 엔티티와 매핑할 테이블 지정
- 생략시 매핑한 엔티티 이름을 테이블 이름으로 사용 (다르다면 꼭 추가)
- 속성
- name : 테이블 이름
- catalog : catalog 기능이 있는 데이터베이스에서 catalog를 매핑 (??)
- schema : schema 기능이 있는 디비에서 스키마 매핑
- unuqueConstraints : DDL 생성 시 유니크 제약조건을 만든다. 2개 이상의 복합 유니크 제약조건도 만들 수 있음. 참고로 이 기능은 스키마 자동 생성 기능을 사용해서 DDL 만들 때만 사용
4.3 다양한 매핑 사용
- @Enumerated : enum 타입 시 사용
- @Temporal : 날짜 타입 시 사용
- @Lob : 길이 제한 없을 시 VARCHAR와 같은 타입 대신 CLOM 타입을 사용해야하는데 이때 @Lob 어노테이션 사용
4.4 데이터베이스 스키마 자동생성
- JPA는 디비 스키마를 자동 생성하는 기능 제공
- 자동 생성 가능한 이유는 클래스의 매핑 정보와 디비 방언을 사용해서 스키마를 생성
- 2강에서 정리했던 yml 의 ddl-auto -> none / create-drop / create / update / validate 해당 설정을 통해 애플리케이션 실행 시점에 디비 테이블을 자동으로 생성하며 show_sql = true 설정 시 콘솔에 실행되는 DDL을 출력
- 하지만 해당 DDL은 운영 환경에서 사용할 만큼 완벽하지는 않으므로 개발환경에서만 사용할 것
- HBM2DDL 주의사항 (https://velog.io/@think2wice/Hibernate-hbm2ddl.auto-프로퍼티-설정)
- 운영 서버에서 create, create-drop, update 처럼 DDL을 수정하는 옵션은 절대 사용 x
- 추천 전략
- 개발 초기 단계 create or update
- 초기화 상태로 자동화된 테스트 진행 환경 시 CI 서버는 create or create-drop
- 테스트 서버 update or validate
- 스테이징과 운영 서버는 validate 또는 none
- 이름 매핑 전략 변경하기
- 자바 관례상 카멜케이스 / 디비 스네이크케이스 -> @Column 어노테이션으로 해결
4.5 DDL 생성 기능
- @Column
- nullable 속성 값 false == not null
- length 속성 값 == 길이 제한 가능
- @Table
- uniqueConstraints 해당 속성값을 사용하연 유니크 제약조건을 추가함
- 해당 속성 값들을 사용하면 단지 DDL을 자동 생성할 때만 사용되고 JPA의 실행 로직에는 영향을 주지 않는다. -> 따라서 자동 생성 기능을 사용하지 않고 직접 DDL을 만든다면 사용할 이유가 없다
- 하지만 이 기능을 사용하면 개발자 입장에서 엔티티만 보고도 손쉽게 다양한 제약 조건을 파악할 수 있는 장점이 있다.
4.6 기본 키 매핑
- 기본 키를 애플리케이션에서 직접 할당하는 대신에 디비가 생성해주는 값을 사용하려면?
- 직접할당 방식과 자동생성 방식 존재 (JPA가 제공해주는 기본 키 생성 전략)
- 자동생성
- IDENTITY : 기본 키 생성을 디비에 위임
- SEQUENCE : 디비 시퀀스를 사용해서 기본키 할당
- TABLE : 키 생성 테이블 사용
- 이렇게 다양한 이유는 디비 벤더마다 지원 방식이 다르기 때문
- 오라클은 시퀀스 제공하지만 mySql 제공안함
- 따라서 sequence나 identity 전략은 사용하는 디비에 의존
- TABLE 전략은 키 생성용 테이블을 하나 만들어두고 마치 시퀀스처럼 사용하는 방법 (이건 모든 디비에서 사용가능)
- 기본 키를 직접 할당하려면 @Id만 사용하면 됨
- 자동 생성 전략을 사용하려면 @Id에 @GeneratedValue 추가 후 원하는 키 생성 전략 입력
4.6.1 기본 키 직접 할당 전략
- 기본 키 직접 할당 전략에서 식별자 값 없이 저장하면 예외가 발생
- 하이버네이트를 구현체로 사용 시 JPA 최상위 예외인 javax.persistence.PersistenceException 이 발생
4.6.2 IDENTITY 전략
- 해당 전략은 기본 키 생성을 디비에 위임하는 전략이다
- 주로 MySQL, PostgreSQL, SQL Server, DB2에서 사용
- MySQL의 AUTO_INCREMENT 기능은 디비가 기본 키를 자동 생성
- 해당 전략 사용이 @GeneratedValue의 strategy 속성 값을 GenerationType.IDENTITY로 지정하면 된다.
- 최적화
- IDENTITY 전략은 데이터를 디비에 INSERT한 후에 기본 키 값을 조회할 수 있다.
- 따라서 엔티티에 식별자 값을 할당하려면 JPA는 추가로 디비를 조회해야한다.
- JDBC3에 추가된 Statement.getGeneratedKeys()를 사용하면 데이터를 저장하는 동시 생성된 기본키 값도 얻어 올 수 있어 이 메서드를 사용해서 디비와 한 번만 통신이 가능하다.
- 주의점 : 엔티티가 영속 상태가 되려면 식별자 반드시 필요 -> 그런데 IDENTITY 식별자 생성 전략은 엔티티를 디비에 저장해야 식별자 구할 수 있으므로 em.persist() 호출하는 즉시 insert sql이 디비에 전달되므로 이 전략은 트랜잭션을 지원하는 쓰기 지연이 동작하지 않는다.
4.6.3 SEQUENCE 전략
- 디비 시퀀스는 유일한 값을 순서대로 생성하는 특별한 디비 오브젝트
- 해당 전략은 이 시퀀스를 사용해서 기본 키 생성
- 해당 전략은 시퀀스를 지원하는 오라클, PostgreSQL, DB2, H2 에서 사용 가능
- @SequenceGenerator를 사용하여 시퀀스 생성기 등록 필요
- 해당 전략은 IDENTITY 전략과 같지만 내부 동작 방식은 다르다
- IDENTITY 전략과 다르게 먼저 디비 시퀀스를 사용해 식별자를 조회하고 엔티티에 식별자 할당 후 엔티티를 영속성 컨텍스트에 저장 이후 트랜잭션 커밋해서 플러시가 일어나면 엔티티를 디비에 저장 -> IDENTITY 전략은 먼저 엔티티 디비에 저장한 후에 식별자를 조회에서 엔티티의 식별자에 할당
- @SequenceGenerator
- SEQUENCE 전략과 최적화
- 해당 전략은 디비 시퀀스를 통해 식별자를 조회하는 추가 작업이 필요하여 디비와 2번 통신
- JPA는 시퀀스에 접근하는 횟수를 줄이기 위해 @SequenceGenerator.allocationSize를 사용
- 해당 사이즈에 설정한 값만큼 한 번에 시퀀스 값을 증가시키고 나서 메모리에 시퀀스 값 할당
- 해당 방법은 시퀀스 값을 선점하므로 여러 JVM이 동시에 동작해도 기본 키 값이 충돌 안하는 장점
- 반면 디비에 직접 접근해서 데이터를 등록할 때 시퀀스 값이 한번에 많이 증가한다는 점 염두해 둘 것
4.6.4 TABLE 전략
- 해당 전략은 키 생성 전용 테이블을 하나 만들고 여기에 이름과 값으로 사용할 컬럼을 만들어 디비 시퀀스를 흉내내는 전략
- 해당 전략은 모든 디비에 적용 가능
- 해당 전략을 사용하기 위해 다음과 같이 테이블 생성 필요
- sequence_name : 해당 컬럼을 시퀀스 이름으로 사용
- next_val : 해당 컬럼을 시퀀스 값으로 사용
- @TableGenerator를 사용하여 테이블 키 생성기를 등록
- @TableGenerator 속성 정리
- name : 식별자생성기 이름
- table : 키생성 테이블영
- pkColumnName : 시퀀스컬럼명
- valueColumnName : 시퀀스값컬럼명
- pkColumnValue : 키로사용할값이름
- initialValue : 초기 값, 마지막으로 생성된 값이 기준
- allocationSize : 시권스 한 변 호출에 증가하는 수(성능 최적 화에사용됨)
- catalog, schema : 데이터베이스 catalog, schema 이름
- uniqueConstrainls(DDL) :유니크제약조건을지정
- TABLE 전략과 최적화
- 해당 전략은 값을 조회하면서 SELECT 쿼리를 사용하고 다음 값으로 증가시키기 위해 UPDATE를 사용한다.
- SEQUENCE 전략과 비교하여 디비를 한 번 더 통신하는 단점이 있음
- 최적화 위해 @TableGenerator.allocatioSize 사용
4.6.5 AUTO 전략
- AUTO는 선택한 디비 방언에 따라 IDENTITY, SEQUENCE, TABLE 전략 중 하나를 자동으로 선택
- 예 ) 오라클 -> SEQUENCE, MySQL -> IDENTITY
- @GeneratedValue의 기본값 AUTO
- 영속성 컨텍스트는 엔티티를 식별자 값으로 구분하므로 엔티티를 영속 상태로 만들려면 식별자 값이 반드시 있어야함 -> em.persist() 호출 후 발생하는 일을 식별자 할당 전략 별로 정리하면 다음과 같음
- 직접 할당 : 호출 전 앱에서 직접 식별자 값을 할당해야 함. 식별자 값 없을 시 예외 발생
- 시퀀스 : 디비 시퀀스에서 식별자 값을 획득 후 영속성 컨텍스트에 저장
- IDENTITY : 디비에 엔티티를 저장해서 식별자 값을 획득한 후 영속성 컨텍스트에 저장 (테이블에 데이터를 저장해야 식별자 값 획득 가능하므로)
- TABLE : 디비 시퀀스 생성용 테이블에서 식별자 값을 획득한 후 영속성 컨텍스트에 저장
- 권장하는 식별자 선택 전략
- 디비 기본 키는 다음 3가지 조건 만족
- null 값은 허용하지 않는다
- 유일해야 한다
- 변해서는 안된다
- 테이블의 기본 키를 선택하는 전략은 크게 2가지
- 자연키 : 비즈니스에 의미가 있는 키 (주민번호, 이메일, 전화번호)
- 대리키 : 비즈니스와 관련 없는 임의로 만들어진 키, 대체 키로도 불림 (오라클 시퀀스, auto_increment)
- 자연 키보다는 대리 키를 권장
- 자연 키 선택 시 유일하긴 하지만 해당 값이 없을 수도 있고 변경될 수도 있기에 (전화번호가 변경되는 것처럼)
- 비즈니스 환경은 언젠가 변하므로 대체키 권장
- JPA는 모든 엔티티에 일관된 방식으로 대리 키 사용을 권장
- 2개 이상의 컬럼으로 기본 키를 구성하는 복합키도 존재
- 디비 기본 키는 다음 3가지 조건 만족
'Book' 카테고리의 다른 글
자바 ORM 표준 JPA 프로그래밍 - JPA 정리하기 (5-1) 연관관계 매핑 기초 (0) | 2022.08.01 |
---|---|
자바 ORM 표준 JPA 프로그래밍 - JPA 정리하기 (4-2) 엔티티 매핑 (0) | 2022.07.27 |
자바 ORM 표준 JPA 프로그래밍 - JPA 정리하기 (3) JPA 시작 (0) | 2022.07.13 |
자바 ORM 표준 JPA 프로그래밍 - JPA 정리하기 (2) JPA 시작 (0) | 2022.07.10 |
자바 ORM 표준 JPA 프로그래밍 - JPA 정리하기 (1) JPA 소개 (0) | 2022.07.03 |
댓글