Entity Mapping

엔티티 매핑 기본

  • Entity - Table 매핑 : @Entity, @Table
  • Field - Column 매핑 : @Column
  • PK(식별자) 매핑 : @Id
  • 연관관계 매핑
    • Table의 FK 매핑 : @JoinColumn
    • 다대일 : @ManyToOne
    • 일대다 : @OneToMany
    • 일대일 : @OneToOne
    • 다대다 : @ManyToMany (실무에서 사용 X, 일대다 + 다대일 로 풀어냄)

DB Schema 자동 생성

스키마 자동 생성

  • JPA매핑정보만 알고 있다면 어떤 Table 인지, 어떤 query를 만들어야 할지 알고 있음
  • 그에 따라 JPA는 Application 로딩 시점에 DB Table을 생성해주는 기능도 지원 → 스키마 자동 생성 ⇒ 직접 table을 생성하고 설정하고 할 필요가 없음
  • 이를 통해 테이블 중심 개발에서 벗어나 객체 중심으로 개발이 가능
  • 데이터베이스 방언(Dialect)을 활용하여 각각의 데이터베이스에 맞는 적절한 DDL 생성
  • 개발 단계에서 사용하는 것을 권장 (운영 시 사용 X)
  • 사용 방법 (JPA설정 파일인 persistence.xml 에서 설정 ← Maven)
    • hibernate.hbm2ddl.auto 의 속성 설정
    • value (설정 값)
      • create : 기존 테이블 삭제 후 다시 생성 (drop and create)
      • create-drop : create와 동일하게 동작하나 종료 시점에 테이블 Drop
      • update : 변경분만 반영 (alter Table)
        • Entity의 Field를 추가하면 alter table로 반영
        • But, Field를 지우는 것은 반영되지 않음
        • [주의] 운영DB에는 사용하면 안됨!
      • validate : 엔티티와 테이블이 정상 매핑되었는지만 확인
        • Entity에는 있는 Field가 Table에는 없다면 Error 발생 → 검증
      • none : 사용하지 않음 (속성 설정 부분을 삭제한 경우와 동일)
  • DDL 생성 기능의 부가적인 기능
    • JPA, Application에 영향을 주는 것이 아닌, 오로지 DB에만 영향을 주는 기능 → 생성 시 DB의 Table이나 Column에 제약조건을 거는것
    • 즉, DDL을 생성할 때만 사용되고 JPA의 실행 로직에는 영향을 주지 않는 것
    • 제약조건 추가
      • @Columnnullable(필수값), length(최대길이 지정)
      • @TableuniqueConstraints → 유니크 제약조건 추가

사용 주의점

  • 운영에서는 절대 create, create-drop, update 사용 XXX
  • 개발 초기 단계에서는 create 또는 update 사용
  • 테스트 서버에서는 update 또는 validate 사용
  • 스테이징과 운영서버는 validate 또는 none 사용
  • 근데 운영서버에서는 왠만하면 사용하지말자! (none) → 테이블이 다 날라가버리는 위험이 존재!

객체 ↔ 테이블 매핑

@Entity

@Entity
public class Member { ... }
  • 정의
    • @Entity 가 붙은 Class(객체)는 엔티티라 부름
    • JPA가 관리한다는 뜻
    • JPA를 통해 Table과 매핑할 Class는 @Entity 필수
  • 주의점
    • 기본 생성자 필수 → JPA가 이를 동적으로 활용(프록시 생성 등..)하게 하기 위함
    • final, enum, interface, inner Class 에는 Entity로 설정할 수 없음
    • 저장하고자 하는 Field에 final 사용 불가

@Table

@Entity
@Table(name = "BASIC_USER")
public class Member { ... }
  • 엔티티와 매핑할 테이블을 지정할 때 사용
  • 속성
    • name : 매핑할 테이블 이름 (기본값 : 엔티티 이름 사용)
    • catalog : DB catalog 매핑
    • schema : DB schema 매핑
    • uniqueConstraints (DDL) : DDL 생성 시 유니크 제약 조건 생성

필드 ↔ 컬럼 매핑

@Column

@Column(name="username", unique = true, length = 10, ...)
private String name;
  • DB Table의 컬럼 매핑
  • 속성
    • name
      • 필드와 매핑할 테이블의 컬럼 이름 지정
      • 기본값 : Field 명
      • name = “username”
    • insertable/updatable
      • 등록/변경 가능 여부
      • insert/update할 때 해당 column을 등록/변경할 것인지 말것인지 정하는 것
      • 변경되서는 안되는 주요 Field 에서 자주 사용
      • 기본값 : true
      • updateable = false
    • nullable (DDL)
      • null 값의 허용 여부 설정.
      • DDL 생성 시에만 영향을 미치는 속성
      • nullable = false → 해당 column은 null이면 안되는 제약조건
    • unique (DDL)
      • 한 컬럼에 간단히 유니크 제약조건을 걸 때 사용.
      • 잘 사용하지 않는 속성 → 해당 속성 대신 @TableuniqueConstraints를 사용
      • DDL 생성 시에만 영향을 미치는 속성
    • columnDefinition(DDL)
      • 데이터베이스 컬럼 정보를 직접 설정 가능
      • DDL 생성 시에만 영향을 미치는 속성
      • columnDefinition = “varchar(50) default ‘NULL’” → 해당 조건으로 column 생성
      • 기본값 : Field의 Java Type과 Dialect 정보를 사용하여 설정
    • length (DDL)
      • 문자 길이 제약조건
      • Java String Type에만 적용됨
      • 기본값 : 255
      • length = 20
    • precision, scale (DDL)
      • 아주 큰 숫자나 정밀한 소수를 다룰 때 사용
      • BigDecimal 타입에서 사용 (+ BingInteger)
      • precision은 소수점을 포함한 전체 자릿 수, scale은 소수의 자릿 수
      • double, float 타입에는 적용 X
      • 기본값 : precision=19 scale=2

@Enumerated

@Enumerated(EnumType.STRING)
private RoleType roleType;
  • Java Enum Type을 Table에 매핑할 때 사용
  • DB 에는 ENUM 타입이 없기 때문에 대신 String 으로 저장되지만 JAVA 안에서는 Enum 같이 사용할 수 있게 해줌
  • 주의! EnumType.ORDINAL 사용X → ORDINAL은 순서로 저장되기 때문에, 추후 순서가 뒤바뀌거나 새로운 항목이 추가되면 순서가 꼬이게 됨!!!
  • 속성
    • value
      • EnumType.ORDINAL : enum 순서를 데이터베이스에 저장
      • EnumType.STRING : enum 이름을 데이터베이스에 저장
      • 기본값 : EnumType.ORDINAL
      • 주의점 : 항상 EnumType.STRING 으로 사용! 즉, default 말고 항상 EnumType.STRING으로 설정 필요

@Temporal

@Temporal(TemporalType.TIMESTAMP) // 이전
private Date createDate;

private LocalDate createLocalDate; // 최신
  • 날짜타입을 매핑할 때 사용 → 날짜를 어떻게 저장할 것인지를 설정하는 것
  • [참고] Java8 의 LocalDate, LocalDateTime이 생기며 현재는 사용하지 않음LocalDate나 LocalDateTime은 따로 매핑정보를 줄 필요가 없음!!
  • 속성
    • value
      • TemporalType.DATE: 날짜, 데이터베이스 date 타입과 매핑 (2022-08-01) → Java8 LocalDate
      • TemporalType.TIME: 시간, 데이터베이스 time 타입과 매핑 (11:10:59)
      • TemporalType.TIMESTAMP: 날짜와 시간, 데이터베이스 timestamp 타입과 매핑 (2022-08-01 11:10:59) → Java8 LocalDateTime

@Lob

@Lob
private String description;
  • varchar 의 범위를 넘어서는 큰 용량의 글을 저장할 때 사용
  • 데이터베이스 BLOB, CLOB Type과 매핑
  • 속성 없음
  • 매핑되는 Field 타입이 문자 → CLOB 과 매핑 (나머지는 BLOB과 매핑)
    • CLOB: String, char[], java.sql.CLOB
    • BLOB: byte[], java.sql. BLOB

@Transient

@Transient
private int temp;
  • DB 에 반영되지 않는, 해당 Field 는 Application 메모리에서만 사용하겠다는 선언
  • 필드 매핑X → 데이터베이스에 저장X, 조회X
  • 주로 메모리상에서만 임시로 어떤 값을 보관하고 싶을 때 사용

기본키(PK) 매핑

@Id

@Id
private Long id;
  • 지정 Field를 PK(Primary Key)로 사용하겠다는 뜻
  • 필수 값영속성 컨텍스트(1차 캐시)에서 Map으로 해당 id 값을 key 로 사용하고 Entity 를 value 로 사용하여 저장하기 때문
  • 위와 같이 @Id 어노태이션만 사용하면 Id를 직접 할당해 줘야함 (setId(…))
    • @GeneratedValue 와 함께 사용 시 자동 생성

@GeneratedValue

@Id @GeneratedValue(strategy = ...)
private Long id;
  • 해당 Field의 id값(PK) 자동 생성 해주는 어노테이션
  • 3가지 전략
    1. IDENTITY
      • @GeneratedValue(strategy = GenerationType.IDENTITY)
      • 기본 키(PK) 생성을 데이터베이스에 위임 (DB에서 id값을 설정하는 것 → 즉, DB에 저장이 되어야 Id 값을 알 수 있음)
      • MySQL, PostgreSQL, SQL Server, DB2 에서 사용 (MySQL → AUTO_ INCREMENT)
    2. SEQUENCE

       ...
       @SequenceGenerator(
               name = "MEMBER_SEQ_GENERATOR",
               sequenceName = "MEMBER_SEQ", // 매핑할 데이터베이스 시퀀스 이름
               initialValue = 1, allocationSize = 1 )
       public class User {
       	@Id 
         @GeneratedValue(strategy = GenerationType.SEQUENCE,
                         generator = "MEMBER_SEQ_GENERATOR") // 해당 시퀀스 rule 을 따르게 됨
         private Long id;
       }
      
      • 데이터베이스 시퀀스 오브젝트 사용
      • @SequenceGenerator 필요
        • 만약 각 테이블마다의 시퀀스를 사용하고 싶을 때 사용
        • 해당 전략을 사용하면 Entity 를 저장하기 직전에 DB에 있는 지정된 시퀀스의 다음 값을 가져오게 됨 (DB로 시퀀스값을 요청해오는 것) → SQL: call next value for MEMBER_SEQ
        • 이름(name), 매핑할 DB 시퀀스 이름(sequenceName), 시작값(initialValue → DDL 생성 시에만 사용), 미리 땡겨올 씨퀀스 크기(allocationSize) 지정
        • 사용하지 않으면 기본 시퀀스 사용 → 모든 Table이 공유하는 시퀀스 (ex_hibernate_sequence)
      • 데이터베이스 시퀀스유일한 값을 순서대로 생성하는 특별한 데이터베이스 오브젝트
      • ORACLE, PostgreSQL, DB2, H2 데이터베이스에서 사용
    3. TABLE

       @Entity
       @TableGenerator(
       			 name = "MEMBER_SEQ_GENERATOR",
       			 table = "MY_SEQUENCES",
       			 pkColumnValue = "MEMBER_SEQ", allocationSize = 1)
       public class Member {
       	 @Id
       	 @GeneratedValue(strategy = GenerationType.TABLE,
       									 generator = "MEMBER_SEQ_GENERATOR")
       	 private Long id;
       }
      
      • 키 생성 전용 테이블을 하나 만들어서 데이터베이스 시퀀스를 흉내내는 전략
      • @TableGenerator 필요
      • 모든 DB에서 사용 가능
      • 하지만 성능에 있어서 좋지 않아 많이 쓰지는 않는 전략
    4. AUTO
      • 방언에 따라 자동 지정
      • ORACLE → SEQUENCE / MYSQL → IDENTITY
      • @GneratedValue 기본 값