Spring

[JPA 기본편] 엔티티 매핑

gogi masidda 2024. 6. 18. 01:21
  • 객체와 테이블 매핑: @Entity, @Table
  • 필드와 컬럼 매핑: @Column
  • 기본 키 매핑: @Id
  • 연관 관계 매핑: @ManyToOne, @JoinColumn

객체와 테이블 매핑

@Entity

  • @Entity가 붙은 클래스는 JPA가 관리하고, 엔티티라 한다.
  • 기본 생성자가 필수다.(public이나 protected)
  • JPA를 사용해서 테이블과 매핑할 클래스는 @Entity가 필수다.
  • 속성: name
    • JPA에서 사용할 엔티티의 이름을 지정
    • 기본 값은 클래스 이름을 그대로 사용
    • 같은 클래스 이름이 없으면 가급적 기본값을 사용한다. 

@Table

  • 엔티티와 매핑할 테이블 지정
  • 속성
    • name: 매핑할 테이블 이름. 기본값은 엔티티 이름을 사용
    • catalog: 데이터베이스 catalog 매핑
    • schema: 데이터 베이스 schema 매핑
    • uniqueConstraints: DDL 생성 시에 유니크 제약 조건 생성 

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

객체에서 매핑을 다 해두면 애플리케이션 실행 시점에 테이블을 자동 생성해준다. 

이렇게 생성된 DDL은 개발에서만 사용해야 하고, 운영에서는 사용하면 안된다. 

데이터베이스 방언대로 해준다. 

 

이 옵션을 키면 적용된다.

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

value 옵션

  • create: 기존 테이블 삭제 후 다시 생성
  • create-drop: create와 같으니ㅏ 종료 시점에 테이블 drop
  • update: 변경부분만 반영
  • validate: 엔티티와 테이블이 정상 매핑되었는지만 확인
  • none: 사용하지 않음

운영 장비에는 절대 create, create-drop, update를 사용하면 안된다. 

개발 초기 단계는 create나 update

테스트 서버는 update 또는 validate

스테이징과 운영 서버는 validate 또는 none

 

필드와 컬럼 매핑

@Entity
public class Member {
    @Id
    private Long id;

    @Column(name = "name")
    private String username;

    private Integer age;

    @Enumerated(EnumType.STRING)
    private RoleType roleType;
    @Temporal(TemporalType.TIMESTAMP)
    private Date createdDate;
    @Temporal(TemporalType.TIMESTAMP)
    private Date lastModifiedDate;
    @Lob
    private String description;
  • @Column
    • 컬럼 매핑
    • 속성
      • name
        • 필드와 매핑할 테이블의 컬럼명
        • 기본 값은 객체의 필드 이름
      • updatable
        • 등록, 변경 가능 여부
        • 기본값은 True
      • nullable
        • null값의 허용 여부를 설정.
        • false로 설정하면 DDL 생성 시에 not null 제약 조건이 붙음.
      • unique
        • 이름이 이상하게 나와서 잘 사용하지 않음.
        • 대신 @Table에서 uniqueConstraints를 사용함.
      • length
      • columnDefinition
        • 컬럼 정보를 직접 줄 수 있음.
      • precision, scale
        • BigDecimal 타입에서 사용
  • @Temporal
    • 날짜 타입 매핑
    • LocalDate, LocalDateTime 사용하면 필요 없음.
  • @Enumerated
    • enum 타입 매핑
    • ORDINAL
      • enum의 순서를 데이터베이스에 저장
      • 사용X
    • STRING
      • enum의 이름을 데이터베이스에 저장
  • @Lob
    • BLOB, CLOB 매핑
    • 매핑하는 타입이 문자면 CLOB으로 매핑
    • 나머지는 BLOB으로 매핑 
  • @Transient
    • 특정 필드를 컬럼에 매핑하지 않음.

기본 키 매핑

  • @Id
    • 직접 할당 
  • @GeneratedValue 
    • 자동 생성
    • 전략 (strategy = ...)
      • IDENTITY
        • 기본 키 생성을 데이터베이스에 위임
        • Insert SQL을 통해 DB에 들어가야 Id값을 알 수 있다. 
          • 그래서 이 전략만 예외적으로 persist()를 호출하는 시점에 insert 쿼리가 날아간다. (원래는 커밋 시점에)
      • SEQUENCE
        • Sequence object를 만들어두고, 그것을 통해서 값을 가져오고 Id 값을 세팅 
        • 매번 값을 가져오면 성능 문제가 있을 수 있음
          • => allocationSize로 먼저 몇개의 값을 한번에 가져올지 설정 가능 
          • 그러면 DB 접근을 최소화하여 성능 저하를 최소로 할 수 있음. 
      • TABLE
        • 키 생성 전용 테이블을 하나 만들어서 데이터베이스 시퀀스를 흉내내는 전략
        • 이 전략도 SEQUENCE와 마찬가지로 allocationSize로 성능 저하를 줄일 수 있음. 

권장하는 식별자 전략

  • 기본 키 제약 조건: null 아님 + 유일 + 변하면 안됨
  • 미래까지 변하지 않는 키를 찾기 어렵다. (대리키를 사용해야 한다)
    • 주민등록번호도 기본 키로 적절하지 않다.
    • 비즈니스 로직과 관련 없는 것으로
  • 권장: Long 형 + 대체키 + 키 생성 전략 사용

 

이렇게 데이터베이스 테이블에서의 외래키를 구현하기 위해 Order에는 memberId, OrderItem에는 orderId, itemId이라는 필드를 만들어 구현할 수도 있다. 하지만, 이런 방식은 만약 Order에서 Member를 찾으려면 Order를 통해 memberId를 찾고, memberId로 Member를 찾아야 한다. 이런 방식은 객체 지향스럽지 않다. 그래서 연관관계 매핑을 통해 외래키로 ...Id를 갖는 것이 아니라, 객체를 갖도록 할 수 있다.

728x90