본문 바로가기
spring/jpa

자바 ORM 표준 JPA 프로그래밍 - 4장 엔티티 매핑

by 쭈꾸마뇽 2021. 6. 24.

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

JPA는 스키마를 자동으로 생성하는 기능을 지원한다.  

spring:  
  jpa:
    hibernate:
      ddl-auto: create // create-drop, update, validate, none(default)

이 설정을 추가하면 애플리케이션 실행 시점에 데이터베이스 테이블을 자동으로 조건에 맞게 생성, 수정, 검증 등 작업을 해준다.

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

JPA 대표 애노테이션

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

객체와 테이블 매핑

@Entity

JPA를 사용해서 테이블과 매핑할 클래스는 @Entity 애노테이션을 필수로 붙여야 한다.

속성 기능 기본값
name JPA에서 사용할 엔티티 이름 지정 설정하지 않으면 클래스 이름 그대로 사용
  • 기본생성자는 필수
  • final 클래스, enum, interface, inner 클래스 사용 불가
  • 필드에 final 사용 불가

@Table

엔티티와 매핑할 테이블 이름을 지정할 때 사용

속성 기능 기본값
name 매핑할 테이블 이름 엔티티 이름을 사용
catalog catalog 기능이 있는 DB에 catalog를 매핑  
schema schema 기능이 있는 DB에 schema를 매핑  
uniqueConstaint DDL 생성 시 유니크 제약조건 생성  
  • @Table에 name 지정

  • @Table에 uniqueConstraints 지정

@Entity와 @Table 동시에 name을 붙였을 경우

@Entity의 name은 순수하게 entity의 이름을 지정하는 것이고 @Table의 name은 DB와 매핑할 테이블 이름을 설정하는 것이다.  즉, 실제로 테이블과 직접적으로 매핑되는 속성은 @Table이므로 둘 다 지정한 경우에는 @Table의 name으로 DB 테이블이 생성된다.

@Entity와 @Table에 name을 지정하여 테이블 이름을 정할 수 있다.  name값을 카멜케이스로 지정했지만 실제 테이블은 언더바 형식으로 생성되는 경우가 있는데 이때는 yml에 설정값을 다음과 같이 추가해야한다.
datasource:   
  hibernate:
    naming:
      physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl​

 


기본 키 매핑

기본 키를 매핑할 때는 @Id를 사용한다.  그리고 위에서의 예제들 모두 @Id를 사용해 기본키를 매핑했다.  단순히 @Id만 사용하는 경우 사용자가 기본키를 직접 할당해 주어야하지만 데이터베이스가 생성해 주는 값을 할당하기 위해서 추가 옵션이 필요하다.

  • IDENTITY : 기본 키 생성을 데이터베이스에 위임
  • SEQUENCE : 데이터베이스 시쿼스를 사용해서 기본 키를 할당
  • TABLE : 키 생성 테이블을 사용

자동 생성 전략이 이렇게 다양한 이유는 DB 벤더마다 지원하는 방식이 다르기 때문에다.  예를 들어 오라클은 시쿼스를 제공하지만 MySql은 제공하지 않는다.

키 생성 전략을 사용하려면 아래 옵션을 추가해줘야 한다.
spring:
  jpa:
    properties:
      hibernate:
        use-new-id-generator-mappings: true​​

기본 키 직접 할당 전략

기본키를 직접 할당하려면 다음 코드와 같이 @Id로 매핑하면 된다.

@Id 적용 가능 자바 타입
◾ 자바 기본형
◾ 자바 래퍼형
◾ String
◾ java.util.Date
◾ java.sql.Date
◾ java.math.BigDeciaml
◾ java.math.BigInteger

IDENTITY 전략

IDENTITY는 기본 키 생성을 데이터베이스에 위임하는 전략이다. 

IDENTITY 전략의 경우 기본 키를 DB에서 생성하기 때문에 생성자나 Setter로 Id를 초기화해 줄 필요가 없다.

Id를 초기화하게 되는 경우 JPA는 DB에 이 값이 있다고 받아들여서 영속성 컨텍스트에서 찾고 DB에서 찾게 되는데 사실 없기 때문에 에러가 발생한다.

org.hibernate.PersistentObjectException: detached entity passed to persist: learn.jpa.model.MemberIdentity

SEQUENCE 전략

데이터베이스 시퀀스는 유일한 값을 순서대로 생성하는 데이터베이스 오브젝트다.  SEQUENCE 전략은 이 시퀀스를 사용해서 기본키를 생성한다.  MySql은 이 모드를 지원하지 않아서 사용할 수 없다

속성 기능 기본값
name 식별자 생성기 이름 필수
sequenceName 데이터베이스에 등록되어 있는 시쿼스 이름 hibernate_sequence
initialValue DDL 생성 시에만 사용됨, 시쿼스 DDL을 생성할 때 처음 시작하는 수를 지정한다. 1
allocationSize 시퀀스 한번 호출에 증가하는 수 50
catalog.schema 데이터베이스 catalog, schema 이름  

Table 전략

Table 전략은 키 생성 전용 테이블을 하나 만들고 여기에 이름과 값으로 사용할 컬럼을 만들어 데이터베이스 시퀀스를 흉내내는 전력이다.  이 전략은 테이블을 사용하므로 모든 데이터베이스에 적용할 수 있다.

속성 기능 기본값
name 식별자 생성기 이름 필수
table 키생성 테이블 명 hibernate_sequence
pkColumnName 시퀀스 컬러명 sequence_name
valueColumnName 시퀀스 값 컬럼명 next_val
pkColumnValue 초기값, 마지막으로 생성된 값이 기준이다 0
allocationSize 시퀀스 한 번 호출에 증가하는 수 50
catalog, schema 데이터베이스 catalog, schema 이름  
uniqueConstaints 유니크 제약조건을 지정할 수 있다.  

Auto 전략

데이터베이스의 종류도 많고 기본 키를 만드는 법도 다양하다.  Auto 전략은 선택한 데이터베이스 방언에 따라 IDENTITY, SEQUENCE, TABLE 전략 중 하나를 자동으로 선택한다.

EX) 오라클 -> SEQUENCE / MySql -> IDENTITY


필드와 컬럼 매핑

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

@Column

@Column은 객체 필드를 테이블 컬럼에 매핑한다.

속성 기능 기본값
name 필드와 매핑할 테이블의 컬럼 이름 객체 필드 이름
insertable 엔티티 저장시 이 필드도 같이 저장한다.
false로 설정하면 이필드는 데이터베이스에 저장하지 않는다.
false 옵션은 읽기 전용일 때 사용한다.
true
updatable 엔티티 수정시 이 필드도 같이 수정한다.
false로 설정하면 데이터베이스에 수정하지 않는다.
false 옵션은 읽기 전용일 때 사용한다.
true
table 하나의 엔티티를 두 개 이상의 테이블에 매핑할 때 사용한다. 현재 클래스가 매핑된 테이블
nullable null 값의 허용 여부를 설정한다.
false로 설정하면 DDL 생성시에 not null 제약조건이 붙는다
true
unique @Table의 uniqueConstaints와 같지만 한 컬럼에 간단히 유니크 제약조건을 걸 때 사용
두 컬럼 이상 사용하려면 클래스 레벨에서 @Table.uniqueConstaints를 사용
 
columnDefinition 데이터베이스 컬럼 정보를 직접 줄 수 있다. 필드의 자바 타입과 방언정보를 사용해서 적절한 컬럼 타입 생성
length 문자 길이 제약조건. String 타입에만 사용 255
precision, scale BigDecimal 타입에서 사용. precision은 소수점을 포함한 전체 자릿수, scale은 소수의 자리수다.
double, float 에는 적용되지 않는다.
precision = 19
scale = 2

각 필드에 속성을 적용해서 생성된 테이블을 확인할 수 있다.

@Enumerated 

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

속성 기능 기본값
value EnumType.ORDINAL : enum 순서를 데이터베이스에 저장
EnumType.STRING : enum 이름을 데이터베이스에 저장
EnumType.ORDINAL

enum을 사용해서 개발을 할 때는 EnumType을 STRING으로 설정하는 것을 권장한다.  이유는 ORDINAL의 경우 enum의 순서를 숫자로 저장하는데 이는 각 상태값을 DB에서 구분하기 힘들 뿐 더러 중간에 새로운 값이 추가되면 ORDINAL 값이 바뀌기 때문이다.

@Temporal 

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

속성 기능 기본값
value TemporalType.DATE : 날짜, DB date 타입과 매핑
TemporalType.TIME : 시간, DB time 타입과 매핑
TemporalType.TIMESTAMP: 날짜와 시간, DB timestamp와 매핑
TemporalType은 필수로 지정해야함

@Temporal을 생략하면 자바의 Date와 가장 유사한 각 데이터베이스 벤더별 타입에 매핑된다.

  • datetime : MySql
  • timestamp: H2, 오라클, PostgreSQL

@Lob 

데이터베이스 BLOB, CLOB와 매핑한다.  @Lob에는 지정할 수 있는 속성이 없다.  대신에 매핑하는 필드 타입이 문자면 CLOB로 매핑하고 나머지는 BLOB로 매핑한다.

@Transient 

이 필드는 매핑하지 않는다.  따라서 데이터베이스에 저장하지 않고 조회도 하지 않는다.  객체에 임시로 어떤 값을 보관하고 싶을 때 사용

@Access

JPA가 엔티티 데이터에 접근하는 방식을 지정한다.

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

출처 : 자바 ORM 표준 JPA 프로그래밍 스터디

 

klyhyeon/JPAStudy

Contribute to klyhyeon/JPAStudy development by creating an account on GitHub.

github.com

 

댓글