본문 바로가기
Spring Framework/JPA

엔티티 매핑

by 도쿠니 2022. 6. 10.

 

엔티티와 테이블을 매핑하는 어노테이션에 대해서 알아보려고 합니다.

JPA는 다양한 매핑 어노테이션을 지원하는데 크게 4가지로 분류할 수 있습니다

  • 객체와 테이블 매핑
    • @Entity
    • @Table
  • 기본 키 매핑
    • @Id
  • 필드와 컬럼 매핑
    • @Column
  • 연관관계 매핑
    • @ManyToOne, @JoinColumn
    • 연관관계 매핑은 양이 많아 다른 게시물로 정리하도록 하겠습니다.

 


객체와 테이블 매핑

@Entity

  • JPA를 사용해서 테이블과 매핑할 클래스에 @Entity 를 붙입니다.
  • JPA가 관리하는 객체를 Entity라 합니다.

name 속성

  • JPA에서 사용할 엔티티 이름을 지정합니다.
  • 보통 기본값인 클래스 이름을 사용합니다.
    • 다른 패키지에 이름이 같은 엔티티클래스가 존재한다면 이름을 지정해서 충돌을 피해야 합니다.

주의사항

  • 기본 생성자가 필수입니다.
    • 파라미터가 없는 public이나 protected 생성자여야 합니다.
  • final, enum, interface, inner 클래스에는 사용할 수 없습니다.
  • DB에 저장할 필드에 final을 사용하면 안됩니다.

@Table

  • 엔티티와 매핑할 데이터베이스 테이블을 지정합니다.
  • 생략하면 엔티티 이름을 테이블 이름으로 사용합니다.

name 속성

  • 매핑할 테이블 이름을 설정합니다.
  • 기본값은 엔티티 이름입니다.

catalog 속성 , schema 속성

  • catalog 기능이 있는 데이터베이스에서 catalog를 매핑합니다.
  • schema 기능이 있는 데이터베이스에서 schema를 매핑합니다.

uniqueConstraints 속성

  • DDL 생성 시에 유니크 제약조건을 만듭니다.
  • 2개 이상의 복합 유니크 제약조건도 만들 수 있습니다.
  • 이 기능은 스키마 자동생성 기능을 사용해서 DDL을 만들 때만 사용됩니다.
    • JPA를 통해서 테이블을 만들때 적용되는 것이지 미리 만들어둔 테이블에는 적용되지 않습니다.

 


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

  • JPA는 데이터베이스 스키마를 자동으로 생성하는 기능을 지원합니다.
    • 클래스 매핑정보와 데이터베이스 방언을 사용해서 데이터베이스 스키마를 생성합니다.
    • hibernate 설정을 해주어야합니다.
      • 옵션
        • create
          • 기존 테이블을 삭제하고 새로 생성합니다.
          • DROP + CREATE
        • create-drop
          • CREATE와 같지만 애플리케이션 종료 시 생성한 DDL을 제거합니다.
          • CREATE + DROP
        • update
          • 데이터베이스 테이블과 엔티티 매핑정보를 비교해서 변경 사항만 수정합니다.
        • validate
          • 데이터베이스 테이블과 엔티티 매핑정보를 비교해서 차이가 있으면 경고를 남기고 애플리케이션을 실행하지 않습니다. 
          • 차이가 있다해서 DDL을 따로 수정하지는 않습니다.
        • none
          • 자동 생성 기능을 사용하지 않습니다.
      • 사용 시 주의사항
        • DDL을 수정하는 옵션은 운영 서버에서 사용하면 안됩니다. 개발 단계에서만 사용해야합니다.
        • 추천하는 방식
          • 개발 초기 : create or update
          • 초기화 상태로 자동화된 테스트를 진행하는 개발자 환경 및 CI 서버 : create or create-drop
          • 테스트 서버 : update or validate
          • 스테이징과 운영서버 : validate or none
          • 사실 로컬을 제외한 개발 등의 서버는 직접 스크립트를 짜서 데이터베이스에서 반영하는 것을 권장
// 스프링부트 application.yml 기준
spring: jpa: hibernate: ddl-auto: 옵션 설정

 

 


기본 키 매핑

직접 할당

  • 기본키를 어플리케이션에서 직접 할당합니다.
  • 기본키로 사용할 엔티티 필드에 @Id만을 사용하고, 애플리케이션에서 직접 식별자를 만들어 넣는 방식입니다.

자동 생성

  • 대리 키 사용 방식 입니다.
  • @Id와 함께 @GeneratedValue를 함께 사용합니다.

 

IDENTITY

  • 기본 키 생성을 데이터베이스에 위임하는 전략입니다.
    • 주로 MySQL, PostgreSQL, SQL Server, DB2 에서 사용합니다.
    • MySQL 같이 AUTO_INCREMENT 등이 있으면 그것을 사용합니다.
  • 데이터베이스에 값을 저장하고 나서야 기본키 값을 구할 수 있습니다.
    • 데이터베이스가 기본키를 설정하기 때문에 데이터베이스에 값을 저장한 이후에야 애플리케이션은 키본키 값을 알 수 있습니다.
    • 이러한 이유로 이 전략에서 em.persist()를 하면 바로 쿼리를 데이터베이스로 날립니다.(트랜잭션을 지원하는 쓰기전략 지원 x)
    • 다만 select 쿼리는 보내지 않는데, 그 이유는 JDBC3에 추가된 Statement.getGeneratedKeys()를 사용해서 데이터를 저장과 동시에 생성된 기본키 값을 얻어오기 때문입니다. 하이버네이트는 이 메소드를 사용해서 데이터베이스와 한 번만 통신을 합니다.

IDENTITY 전략

SEQUENCE

  • 데이터베이스 시퀀스란 유일한 값을 순서대로 생성하는 특별한 데이터베이스 오브젝트입니다.
    • SEQUENCE 전략은 이 데이터베이스 시퀀스를 사용해서 기본 키를 생성합니다.
    • 시퀀스를 지원하는 Oracle, PostgreSQL, DB2, H2 데이터베이스 등에서 사용할 수 있습니다.
  • 작동 순서
    • em.persist()를 호출할 때 먼저 데이터베이스에서 시퀀스를 사용해 식별자를 조회합니다.
      • IDENTITY와 달리 이때 INSERT 가 날라가지 않습니다.
    • 조회한 식별자를 엔티티에 할당한 후에 엔티티를 영속성 컨텍스트에 저장합니다.
    • 이후 트랜잭션을 커밋해서 flush가 일어나면 엔티티를 데이터베이스에 저장합니다.

SEQUENCE 전략

  • @SequenceGenerator
    • 데이터베이스 시퀀스를 매핑합니다.
    • Sequence 전략을 사용하면 데이터베이스와 2번 통신합니다.
      • 식별자를 구하기 위해 데이터베이스 시퀀스 조회 + 조회환 시퀀스를 기본키 값으로 사용하는 엔티티 저장
      • 10번만 저장해도 20번을 데이터베이스와 통신합니다.
      • 시퀀스에 접근하는 횟수를 줄이기 위해 allocationSize 속성을 이용합니다.
        • 속성에 들어있는 값만큼 한번에 데이터베이스에서 증가시킨 후, 매번 데이터베이스에서 접근하지 않고 그 수만큼 메모리에서 식별자를 할당합니다.
        • 예를 들어 값이 50이면, 한번에 50만큼 시퀀스를 증가시키고 DB에서 50만큼 가져와 메모리에서 할당한 후, 가져온 시퀀스를 다 사용하면 다시 증가시키고 가져와서 사용하는 방식입니다.
        • 일종의 최적화 방법입니다.
    • 속성

TABLE

  • 키 생성 전용 테이블을 만들어서 데이터베이스 시퀀스를 흉내내는 전략
  • 테이블을 사용하므로 모든 데이터베이스에 적용할 수 있습니다.

  • 시퀀스 대신에 테이블을 사용한다는 것만 제외하면 SEQUENCE 전략과 내부 동작방식이 동일합니다.
  • 하나의 키 생성 전용 테이블을 여러 엔티티에서 로우만 다르게 공용하여 사용할 수 있습니다.
    • {pkColumnName} {valueColumnName}
      pkColumnValue1 2
      pkColumnValue2 15
      pkColumnValue3 40
  • 속성

AUTO

  • 선택한 데이터베이스 방언에 따라 위의 세가지 전략 중 하나를 자동으로 선택합니다.
    • 오라클의 경우 SEQUENCE, MySQL의 경우 IDENTITY를 사용하는 등
  • @GeneratedValude의 기본값은 AUTO 입니다.
  • 키 생성 전략이 확정되지 않은 개발 초기 단계나 프로토타입 개발 시 편리하게 사용할 수 있습니다.
  • SEQUENCE나 TABLE 전략이 선택되는 경우, 시퀀스나 키 생성용 테이블을 미리 만들어 두어야 하지만 스키마 자동 생성 기능을 사용한다면 하이버네이트가 기본값을 사용해서 적절하게 만들어 줍니다.

AUTO시 작동 Flow

 


필드와 컬럼 매핑

@Column

  • 객체 필드를 테이블 컬럼에 매핑합니다.
  • 주로 사용되는 속성은 name, nullable 입니다.
  • insertable, updatable 속성은 데이터베이스에 저장되어있는 정보를 읽기만 하고 실수로 변경하는 것을 방지하고 싶을 때 false로 바꾸어 사용합니다.
  • unique는 키가 랜덤한 이름으로 나오기 때문에 잘 사용하지 않습니다.
    • 대신 @Table에 uniqueConstrains 옵션을 주면 이름을 설정할 수 있어서 이 방법을 더 많이 사용합니다.
  • 필드에 @Column을 생략하더라도 테이블 컬럼으로 등록됩니다.
    • 주의할 점은 자바 primitive 타입의 경우 null 값이 허용 안되기 때문에 JPA에서 자동으로 not null 제약을 걸어줍니다.
    • 다만 primitive 타입에 not null 제약조건이 없는 @Column만 붙일 경우, nullable의 기본값이 true이기 때문에 false로 명시적으로 적어주는 것이 안전합니다.

 

@Enumerated

  • 자바 enum 타입을 매핑할 때 사용합니다.
  • value를 STRING으로 사용하도록 합시다!!!!

 

@Temporal

  • 날짜 타입인 java.util.Date, java.util.Calendar를 매핑할 때 사용합니다.
  • 어노테이션을 생략하면 자바의 Date와 가장 유사한 timestamp로 정의됩니다.
    • LocalDate, LocalDateTime을 사용할 때는 어노테이션을 생략해도 됩니다.

 

@Lob

  • 데이터베이스 blob과 clob 타입과 매핑합니다.
  • 매핑하는 필드 타입이 문자면 CLOB, 나머지는 BLOB으로 매핑합니다.

 

@Transient

  • 필드 매핑을 하지 않을 때 사용합니다.
  • 데이터베이스에 저장되거나 조회되지 않습니다.
  • 주로 메모리 상에서 객체에 임시로 값을 보관하고 싶을 때 사용합니다.

 

@Access

  • JPA가 엔티티 데이터에 접근하는 방식을 지정합니다.
  • 생략 시 @Id 위치를 기준으로 접근 방식이 설정됩니다.
  • 접근 방식
    • 필드 접근
      • @Access(AccesType.FIELD)
      • 필드 접근 권한이 private이여도 필드에 직접 접근합니다.
      • @Id가 필드에 붙어있는 경우, 생략 가능합니다.
    • 프로퍼티 접근
      • @Access(AccesType.PROPERTY)
      • Getter를 사용해서 접근합니다.
      • @Id가 Getter에 붙어있는 경우, 생략 가능합니다.

'Spring Framework > JPA' 카테고리의 다른 글

@GeneratedValue 로 UUID 사용하기  (0) 2022.06.13
Transaction (트랜잭션)  (0) 2022.06.10
영속성 관리  (0) 2022.06.10
데이터베이스 방언 (Dialect)  (0) 2022.06.10
JPA 소개  (0) 2022.06.10

댓글