JPA

[JPA] 엔티티 매핑

리승자이 2022. 8. 4. 22:11
728x90

깃허브 바로가기
JPA에서 가장 중요한 것은 엔티티와 테이블 매핑을 정확히 하는 것이다.
매핑 어노테이션을 잘 숙지해야 한다.

  • 객체와 테이블 매핑 : @Entity, @Table
  • 기본 키 매핑 : @Id
  • 필드와 컬럼 매핑 : @Column
  • 연관관계 매핑 : @ManyToOne, @JoinColumn

@Entity

JPA를 사용해서 테이블과 매핑할 클래스는 @Entity 어노테이션을 필수로 붙여야 한다.
@Entity가 붙은 클래스는 JPA가 관리하는 것으로 엔티티라고 부른다.

속성 기능 기본값
name JPA에서 사용할 엔티티 이름을 정한다. 보통 기본값인 클래스 이름을 사용한다. 만약 다른 패키지에 이름이 같은 엔티티 클래스가 있다면 이름을 지정해서 충돌하지 않도록 해야 한다. 설정하지 않으면 클래스 이름 그대로 사용

@Entity 적용시 주의 사항

  • 기본 생성자는 필수(파라미터가 없는 public or protected 생성자)
    • Lombok에서는 @NoArgsConstructor 사용
  • final 클래스, enum, interface, inner 클래스에는 사용할 수 없다.
  • 저장할 필드에 final을 사용하면 안된다.

생성자가 하나도 없을 때 자바는 기본 생성자를 생성하지만, 생성자 오버로딩을 했을 때는 개발자가 직접 기본 생성자를 만들어줘야 한다.

@Table

@Table은 엔티티와 매핑할 테이블을 지정. 생략시 매핑한 엔티티 이름을 테이블 이름으로 사용

속성 기능 기본값
name 매핑할 테이블 이름 엔티티 이름을 사용
catalog catalog 기능이 있는 DB에서 catalog매핑
schema schema 기능이 있는 DB에서 schema 매핑
uniqueConstraints DDL 생성시 유니크 제약조건을 만듦. 2개 이상의 복합 유니크 제약조건도 만들 수 있다. 스키마 자동생성기능을 사용해서 DDL을 만들때만 사용

다양한 매핑

  • @Enumerated : 자바의 enum을 사용할 때
  • @Temporal : 자바의 날짜타입 매핑
  • @LOB : CLOB, BLOB 타입 매핑

DB 스키마 자동생성

JPA는 DB스키마를 자동 생성하는 기능을 지원.

application.yaml

spring:
  jpa:
    hibernate:
      ddl-auto: create

어플리케이션 실행 시점에 DB테이블 자동으로 생성

옵션 설명
create 기존 테이블을 삭제하고 새로 생성, DROP + CREATE
create-drop create 속성에 추가로 어플리케이션을 종료할때 DDL 제거, DROP + CREATE + DROP
update DB 테이블과 엔티티 매핑정보를 비교해서 변경 사항만 수정
validate DB 테이블과 엔티티 매핑정보를 비교해서 차이가 있으면 경로를 남기고 어플리케이션을 실행하지 않는다. 이것은 DDL을 수정하지 않음.
none 자동 생성 기능을 사용하지 않으려면 ddl-auto 속성을 제거하거나 유효하지 않은 옵션 값을 주면 된다.(none은 유효하지 않은 옵션값)

sql보기

spring:
  jpa:
    properties:
      hibernate:
        show_sql: true

DDL생성 기능

@Column 매핑정보의 nullable속성 값을 false로 지정하면 자동 생성되는 DDL에 not null 제약조건을 추가할 수 있다. 자동 생성되는 DDL에 문자 크기를 length옵션으로 지정할 수 있다.

@Table 에 유니크 제약조건을 만들어주는 uniqueConstraints 속성은 유니크 제약조건을 말 그대로 걸어주는 것인데 이 속성들은 DDL을 자동 생성할때만 사용되고 JPA 실행 로직에는 영향을 주지 않는다.

직접 DDL을 만들면 사용할 이유가 없는 속성들이다.
그럼에도 이 기능을 사용한다면 엔티티만 보고도 다양한 제약조건을 파악할 수 있다는 장점이 존재

기본키 매핑

@Entity
public class Member{
    @Id
    @Column(name= "ID")
    private String id;

JPA에서 제공하는 DB 기본키 생성 전략

  • 직접 할당 : 기본 키를 어플리케이션에서 직접 할당
  • 자동 생성 : 대리 키 사용 방식
    • IDENTITY : 기본 키 생성을 DB에 위임
    • SEQUENCE : DB시퀀스를 사용하여 기본 키 할당
    • TABLE : 키 생성 테이블을 사용

자동생성 전략이 다양한 이유는 DB벤더마다 지원하는 방식이달라서 이다.
SEQUENCE나 IDENTITY 전략은 사용하는 DB에 의존

기본키를 할당하려면 @Id 사용, 자동생성 전략을 이용하려면 @GeneratedValue를 사용하면 된다.

IDENTITY 전략

기본 키 생성을 DB에 위임하는 전략
MySQL, Postgre, SQL Server, DB2 에서 사용

@Id
@GeneratedValue(strategy = GenertaionType.IDENTITY)
private Long id;

IDENTITY는 데이터를 DB에 insert한 후에 기본 키 값을 조회할 수 있음.
그러므로 엔티티에 식별자 값을 할당하려면 추가로 DB를 조회해야함

SEQUENCE 전략

유일한 값을 순서대로 생성하는 전략
Oracle, Postgre, DB2, H2 에서 사용 가능
@SequenceGenerator 에 시퀀스 생성기를 name이값에 등록하고
sequenceName 속성 이름으로 DB 시퀀스를 매핑함
그러면서
@GenerateValue(strategy = Generation.Type.SEQUENCE, generator = "SequenceGenerator의 name값")
사용하면 시퀀스 생성기 할당됨

@SequenceGenerator

속성 기능 기본값
name 식별자 생성기 이름 필수
sequenceName DB에 등록된 시퀀스 이름 hibernate_sequence
initialValue DDL 생성시에 사용, 시퀀스 DDL 생성할때 처음 시작하는 수 지정 1
allocationSize 시퀀스 한번 호출에 증가하는수(성능최적화에 사용) 50
catalog, schema 데이터베이스 catalog, schema이름

DDL ex - create sequence [sequenceName] start with [initialValue] increment by [allocationSize]

TABLE 전략

키생성 전용 테이블을 하나 만들고 이름과 값으로 사용할 컬럼 만든후 시퀀스를 흉내내는 전략

create table MY_SEQUENCES {
    sequence_name varchar(255) not null,
    next_val bigint,
    primary key (sequence_name)
}

@GeneratorValue(generator = "BOARD_SEQ_GENERATOR")

@TableGenerator

속성 기능 기본값
name 식별자 생성기 이름 필수
table 키생성 테이블명 hibernate_sequences
pkColumnName 시퀀스 컬럼명 sequence_name
valueColumnName 시퀀스 값 컬럼명 next_val
pkColumnValue 키로 사용할 값 이름 엔티티 이름
initialValue 초기 값, 마지막으로 생성된 값이 기준 0
allocationSize 시퀀스 한번 호출에 증가하는 수(성능 최적화) 50
catalog, schema DB catalog, schema 이름
uniqueConstraints(DDL) 유니크 제약 조건 지정

AUTO 전략

선택한 DB의 방언에 따라 Identity, Sequence, Table 전략중 하나 자동으로 설정

기본키 매핑 정리

영속성 컨텍스트는 엔티티를 식별자 값으로 구분하기 때문에 엔티티를 영속 상태로 만드려면 식별자 값은 반드시 포함해야 하는 사실. em.perist()를 호출한 직후 발생하는일을 정리하면 아래와 같다.

  • 직접 할당
    • em.persist() 를 호출하기 전에 애플리케이션에서 직접 식별자 값 할당
    • 없다면 예외발생
  • SEQUENCE
    • DB 시퀀스에서 식별자 값 획득 후 영속성 컨텍스트에 저장
  • TABLE
    • DB 시퀀스 생성용 테이블에서 식별자 값 획득 후 영속성 컨텍스트 저장
  • IDENTITY
    • DB에 엔티티를 저장한 다음 식별자 값 획득 후 영속성 컨텍스트 저장
    • 테이블에 데이터를 저장해야 식별자 값 획득이 가능

레퍼런스

JPA에서 제공하는 필드와 컬럼 매핑용 어노테이션 정리

분류 매핑 어노테이션 설명
필드와 컬럼 매핑
@Column 컬럼을 매핑
@Enumerated 자바 enum 타입 매핑
@Temporal 날짜 타입 매핑
@Lob CLOB, BLOB 타입 매핑
@Transient 특정 필드를 DB에 매핑하지 않음
기타 @Access JPA가 엔티티에 접근하는 방식 지정

@Column

속성 기능 기본값
name 필드와 매핑할 테이블 컬럼이름 객체의 필드이름
nullable(DDL) null값 허용 여부 설정. false설정 시 DDL조건에 not null제약조건 추가됨 true
unique(DDL) 한 컬럼에 간단히 유니크 제약조건 걸 때 사용, 두 컬럼 이상 사용시 @Table.uniqueConstraints사용
ColumnDefinition(DDL) DB 칼럼 정보 직접 줄 수 있음 필드의 자바 타입과 방언 정보를 사용해서 적절한 컬럼 타입 생성
length(DDL) 문자 길이 제약조건, String타입에만 사용 255
precision, scale(DDL) BigDecimal타입에서 사용 precision은 소수점 포함 전체자리수, scale은 소수 자리수, float이나 double타입에는 적용 안됨 precision = 19, scale= 2

안쓰는 것은 구글링을 해서 찾아야겠다.

@Enumerated

  • EnumType.ORDINAL은 enum정의된 순서대로 0, 1 순서로 DB에 저장
    • 장점 : DB에 저장되는 데이터 크기가 작음
    • 단점 : 이미 저장된 enum의 순서를 변경할 수 없음
  • EnumType.STRING은 enum 이름 그대로 DB에 저장
    • 장점 : 저장된 enum의 순서가 바뀌거나 enum이 추가되어도 안전
    • 단점 : DB에 저장되는 데이터 크기가 ORDINAL에 비해 큼

@Temporal

TemporalType필수 지정

  • value
    • TemporalType.DATE: 날짜, DB date 타입 매핑
    • TemporalType.TIME: 시간, DB time 타입 매핑
    • TemporalType.TIMESTAMP: 날짜와 시간, DB timestamp 타입과 매핑

@Lob

지정할 수 있는 속성이 없음.
대신 매핑하는 필드타입이 문자라면 CLOB으로 매핑 나머지는 BLOB으로 매핑

@Transient

매핑하지 않는 필드, 그렇기 때문에 DB에 저장하지도 않고 조회하지도 않음.
객체에 임시로 어떤 값을 보관하고 싶을 때 사용함.

@Access

엔티티 데이터에 접근하는 방식 지정

  • 필드 접근 : AccessType.FILED로 지정.
    • 필드에 직접 접근, 접근 권한이 private여도 접근 가능
  • 프로퍼티 접근 : AccessType.PROPERTY 로 지정. 접근자(Getter) 사용.

@Access 를 설정하지 않으면 @Id 위치를 기준으로 접근방식 설정

@Id 가 필드에 있으면 @Access(AccessType.FILED) 로 설정한 것과 같음.
그래서 생략 가능

728x90