엔티티 매핑

inho ha·2022년 5월 11일
0

자바 ORM 표준 JPA 프로그래밍

http://www.kyobobook.co.kr/product/detailViewKor.laf?mallGb=KOR&ejkGb=KOR&barcode=9788960777330

매핑 정보 구성 방법

  1. xml 파일로 작성
  2. 어노테이션으로 작성

어노테이션을 사용하는 것이 엔티티 파일에서 바로 확인할 수 있으므로 좀 더 쉽고 직관적이다.

@Entity

테이블과 매핑할 클래스에 붙여줘야한다.
해당 클래스는 기본 생성자(파라미터가 없는 public, protected)가 꼭 있어야한다.
final, enum, interface, inner 클래스에는 사용할 수 없다.
저장할 필드에 final을 사용하면 안된다.

생성자를 하나도 작성하지 않으면 자바가 기본 생성자를 자동으로 만든다.
생성자가 하나 이상 있으면 자바가 기본 생성자를 만들어 주지 않으므로 이 경우 기본 생성자를 직접 작성해줘야한다.

데이터베이스 스키마 자동 생성

JPA는 매핑 정보를 바탕으로 데이터베이스 스키마를 자동으로 생성하는 기능을 지원한다.

persistence.xml 에서 설정 가능하다.

<property name="hibernate.hbm2ddl.auto" value="create" />

value를 create로 설정하면 애플리케이션 실행 시점에 기존 테이블을 삭제하고 다시 생성한다.

value를 create-drop로 설정하면 애플리케이션 실행 시점에 기존 테이블을 삭제하고 다시 생성한다. 이후 애플리케이션 종료할 때 생성한 DDL을 제거한다.

value를 update로 설정하면 애플리케이션 실행 시점에 기존 테이블과 비교하여 변경 사항만 수정한다.

value를 validate로 설정하면 애플리케이션 실행 시점에 기존 테이블과 비교하여 차이가 있으면 경고를 남기고 실행하지 않는다.

운영 서버에서 DDL을 수정하는 옵션은 절대 사용하면 안된다.
개발 서버나 개발 단계에서만 사용해야한다.

create 옵션 운영 서버에 적용해서 데이터베이스 날라간 썰
https://www.youtube.com/watch?v=SWZcrdmmLEU

개발 초기 단계는 create, update
초기화 상태로 자동화된 테스트를 진행하는 개발자 환경, CI 서버는 create, create-drop
테스트 서버는 update, validate
스테이징과 운영서버는 validate, none

JPA 2.1부터는 스키마 자동 생성 기능을 표준으로 지원한다.

이름 매핑 전략

hibernate.ejb.naming_strategy 로 이름 매핑 전략 설정 가능하다.
하이버네이트는 기본적으로 테이블 명이나 컬럼 명이 생략되면 카멜 표기법을 언더스코어 표기법으로 매핑한다.

DDL 생성 기능

@Column(nullable = false, length = 10)
으로 DDL에 not null 제약 사항을 추가하고, 길이를 지정할 수 있다.

@Table(uniqueConstraints = {@UniqueConstraint(name="NAME_AGE_UNIQUE", columnNames = {"NAME", "AGE"})})
으로 컬럼에 유니크 제약 조건을 추가할 수 있다.

이 기능들은 DDL을 자동 생성할 때만 사용되고 JPA 실행 로직에 영향을 주지 않는다.
그래도 이 기능을 사용하면 엔티티만 보고 제약 조건을 파악할 수 있어서 유용하다.

기본 키 매핑

JPA가 제공하는 기본 키 생성 전략

1. 직접 할당

에플리케이션에서 직접 할당한다.

2. 자동 생성

대리키 사용 방식
IDENTITY : 기본 키 생성을 데이터베이스에 위임한다.
SEQUENCE : 데이터베이스 시퀀스를 사용해서 기본 키를 할당한다.
TABLE : 키 생성 테이블을 사용한다.

IDENTITY, SEQUENCE 이 두방식은 데이터베이스 벤더 마다 사용 불가능한 것도 있다.
TABLE 방식은 키 생성용 테이블은 하나 만들어 두고 시퀀스처럼 사용하는 방법이라 모든 데이터베이스에서 사용할 수 있다.

직접 할당하려면 @ID 만 사용하면 되고
자동 할당하려면 @GeneratedValue(원하는 전략) 도 사용하면 된다.

키 생성 전략을 사용하려면 persistence.xml에 hibernate.id.new_generator_mappings=true 속성을 추가해야한다.

하이버네이트는 더 효과적이고 JPA 규격에 맞는 키 생성 전략을 개발했다.
과거 버전과 호환성을 유지하기 위해 옵션은 남겨두고 기본 값을 false로 두었다.
이 옵션을 true로 하면 키 생성 성능을 최적화 하는 allocationSize 속성을 사용하는 방식이 달라진다.

IDENTITY 전략

IDENTITY 전략 사용시 엔티티에 식별자 값을 할당하기 위해 데이터베이스에 저장을 하고 추가로 조회해야한다.

???? 엔티티를 저장한 다음에 식별자 값을 어떻게 알고 조회하는걸까???????? 식별자 값 이외의 필드로 조회를 하는건가??????

하이버네이트는 JDBC3에 추가된 Statement.getGeneratedKeys()를 사용하여 데이터를 저장하면서 동시에 생성된 기본 키 값도 얻어 오도록 최적화 한다.

엔티티가 영속 상태가 되려면 식별자가 반드시 필요하기 때문에 em.persist() 로 저장하는 동시에 insert sql이 데이터 베이스에 전달되어 트랜잭션을 지원하는 쓰기 지연이 동작하지 않는다.

SEQUENCE 전략

데이터베이스 시퀀스는 유일한 값을 순서대로 생성하는 데이터베이스 오브젝트이다.

이 전략은 persist()를 호출할 때 먼저 데이터베이스 시퀀스를 사용해서 식별자를 조회한다.
조회한 식별자를 엔티티에 할당한 후에 엔티티를 영속성 컨텍스트에 저장한다.
이후 플러시가 일어나면 엔티티를 데이터베이스에 저장한다.
따라서 IDENTITY 전략과 달리 트랜잭션을 지원하는 쓰기 지연이 가능하다.

이 전략에서 시퀀스 한 번 호출에 증가하는 수를 설정 가능하다.
기본 값은 50이다.
이는 최적화 떄문이다.

SEQUENCE 전략과 최적화

이 전략은 데이터베이스와 두번 통신한다.
1. 식별자를 구하기 위해 데이터베이스 시퀀스를 조회한다.
2. 조회한 시퀀스를 기본 키 값으로 사용해 데이터베이스에 저장한다.

JPA는 시퀀스에 접근하는 횟수를 줄이기 위해 시퀀스 한 번 호출에 증가하는 수를 50을 기본값으로 설정한다.
시퀀스 값을 50 증가 시키고 나면 50 동안은 시퀀스 조회 없이 메모리에서 식별자를 할당한다.
이렇게 시퀀스 값을 선점하면 여러 JVM이 동시에 동작해도 기본 키 값이 충동하지 않는 장점이 있다.
대신 데이터베이스에 직접 접근해서 데이터를 등록할 때 시퀀스 값이 한번에 많이 증가한다.

hibernate.id.new_generator_mappings=true 로 설정해야 위의 최적화 방법이 적용된다.
그렇지 않으면 하이버네이트가 과거에 사용하던 방법으로 키 생성을 최적화한다.
과거에는 하나씩 할당 받고 애플리케이션에서 allocationSize 만큼 사용했다.

TABLE 전략

키 생성 전용 테이블은 하나 만들고 여기에 이름과 값을 사용할 컬럼을 만들어 데이터베이스 시퀀스를 흉내내는 전략이다.

테이블을 사용하기 때문에 모든 데이터베이스에서 사용가능한 전략이다.
시퀀스 대신에 테이블을 사용할 뿐이지 SEQUENCE 전략과 내부 동작방식이 같다.

TABLE 전략과 최적화

이 전략은 값을 조회하는 쿼리 이후 값을 증가 시키는 업데이트 쿼리를 사용하여 SEQUENCE 전략보다 데이터베이스와 통신을 한 번 더 한다.
@TableGenerator.allocationSize를 사용하면 최적화된다.

AUTO 전략

이 전략을 선택하면 데이터베이스 방언에 따라 자동 전략중에 선택된다.

이 전략의 장점은 데이터베이스를 변경해도 코드를 수정할 필요가 없다는 것이다.
특히 키 생성 전략이 확정되지 않은 초기 단계에 유용하다.

이때 SEQUENCE나 TABLE 전략이 선택되면 시퀀스나 키 생성용 테이블을 만들어둬야 하는데 스키마 자동 생성기능을 사용하면 하이버네이트가 만들어준다.

권장하는 식별자 선택 전략

데이터베이스의 기본 키는

  1. NULL값 안됨
  2. 유일해야함
  3. 변하면 안됨

기본 키를 선택하는 전략

  1. 자연 키

비즈니스에 의미 있는 키 (주민번호, 이메일, 전화번호 등)

  1. 대리 키
    비즈니스와 관련 없는 임의로 만들어진 키(오라클 시퀀스, auto_increment 등)

자연 키 보다는 대리키 권장
전화번호는 없을 수도 있고 변경될 수 도 있기 때문이다.
심지어 주민번호도 변할 수 도 있긴하다.

비즈니스 환경은 언젠가 변한다.
주민번호를 기본 키로 사용하고 이를 외래 키로 다른 테이블에서 가지고 있는 경우가 있었는데 개인정보 정책이 변경되어 주민번호를 저장하지 못하게 되어서 많은 수정이 필요한 경우도 있었다.

대리 키를 기본 키로 사용하고 자연 키의 후보가 되는 컬럼들은 필요에 따라 유니크 인덱스를 설정해서 사용하는 것을 권장한다.

@Column 생략

생략시 기본값이 적용된다.
자바 기본 타입일 때는 not null이 적용된다.
int 같은 자바 기본 타입에는 null을 입력할 수 없기 때문이다.

그런데 자바 기본 타입에 @Column 만 달면 not null이 적용 되지 않아서 이 경우 (nullable = false) 로 설정 해주는 것이 안전하다.

@Enumerated

enum 타입을 매핑할때 사용한다.

이때 주의할 점은 EnumType.ORDINAL 로 설정하면 enum 순서를 저장하여 enum에 다른 값이 추가되어 순서가 변경되면 이미 저장된 enum의 순서와 달라지는 문제가 생긴다.

그래서 EnumType.STRING 으로 설정하는 것을 권장한다.

@Transient

이 필드는 매핑하지 않기 때문에 객체에 임시로 어떤 값을 보관하고 싶을 때 사용한다.

영속성 컨텍스트에는 저장이 될까????????????????

profile
inho ha / ian(swatchon) / iha(42seoul)

0개의 댓글