LostCatBox

(JPA) JPA-Basic-CH03 (엔티티 매핑)

Word count: 852Reading time: 5 min
2023/04/08 Share

엔티티 매핑

엔티티 매핑 소개

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

@Entity

  • @Entity가 붙은 클래스는 JPA가 관리, 엔티티라고 한다.
  • 주의
    • 기본 생성자 필수(파라미터 없는 protected 이상의 생성자)
    • final 클래스, enum, interface, inner 클래스 사용 X
    • 저장할 필드에 final 사용 X

@Table

  • @Table은 엔티티와 매핑할 테이블 지정
  • DB에서 활용할 속성 지정가능 , DDL(생성 시에 유니크 제약 조건 생성)도 가능
  • 스크린샷 2023-04-08 오후 2.38.08

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

  • Application 실행시점에 자동 테이블 생성! 기능지원함(Create 문)
  • 테이블 중심 -> 객체 중심
  • 데이터베이스 방언을 활용해서 데이터베이스에 맞는 적절한 DDL생성(varchar 등등)
  • 이렇게 생성된 DDL은 개발 장비에서만 사용
  • 생성된 DDL은 운영서버에서는 사용 X, 적절히 참고해서 다시 만들기

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

  • 실 업무에서는 none
  • 스키마 자동 생성하기 설정, 방언 별로 달라지는 것 확인 했음

스크린샷 2023-04-08 오후 2.41.43

데이터베이스 스키마 자동 생성 주의!!!

  • 운영 장비에는 절대 create, create-drop, update 사용하면 안된다!!!
  • 개발 초기 단계는 create, update
  • 테스트 서버는 update 또는 validate
  • 스테이징과 운영 서버는 validate 또는 none

update, create 는 DDL에서 create, alter 자체가 운영 서버에 일어나는거면, 반영중에도 서버가 멈출수있다. 따라서 none을 기본으로 하자

DDL 생성 기능

  • 제약조건 추가: 회원 이름은 필수, 10자 초과 X
    • @Column(nullable = false, length = 10)
  • 유니크 제약조건 추가
    • @Table(uniqueConstraints = {@UniqueConstraint( name = "NAME_AGE_UNIQUE",**
**columnNames = {"NAME", "AGE"} )})
  • DDL 생성 기능은 DDL을 자동 생성할 때만 사용되고 JPA의 실행 로직에는 영향을 주지않는다.

필드와 컬럼 매핑

요구사항 추가

  • 회원은 일반 회원과 관리자로 구분
  • 회원 가입일과 수정일있어야한다
  • 회원을 설명할 수있는 필드가 있어야한다. 길이 제한없다
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Entity
@NoArgsConstructor
public class Member {
@Id
private Long id;
@Column(name = "name") //DB에서의 컬럼네임 지정
private String username;
private Integer age;
@Enumerated(EnumType.STRING) //JPA에서 ENUM타입사용시
private RoleType roleType;
@Temporal(TemporalType.TIMESTAMP) // 날짜, 시간 쓸때, Temporal
private Date createdDate;
@Temporal(TemporalType.TIMESTAMP)
private Date lastModifiedDate;
@Lob // DB에서 큰 사이즈 컬럼
private String description;
}

매핑 에너테이션 정리

  • hibernate.hbm2ddl.auto
  • Transient = 특정 필드를 컬럼에 매핑하지않음(매핑 무시)

스크린샷 2023-04-08 오후 3.14.37

@Colum

  • insertable, updatable은 컬럼 수정시, DB에 반영여부 정할수있다.
    • 예를 들어 update table=false 라면, 컬럼 데이터의 update는 할수없다.
  • Nullable 은 DB에 NotNull 제약조건 여부를 선택한다.
  • unique 제약 조건은 필드 단위로는 잘안쓴다.
    오히려 클래스 단위로 uniqueConstraints 설정하여, 네임까지 정함

스크린샷 2023-04-08 오후 3.16.59

@Enumerated

  • 자바 enum 타입을 매핑할 때 사용
  • 주의 ORDINAL 사용 X 위험!!!!!!!!!!!!!!
    • ORDINAL은 순서를 저장하므로 Enum의 스트링 값이 안들어감
    • ENUM에서 갑자기 값이 앞뒤로 추가된다면, 순서에 의존하기때문에, 읽을때 정보가 달라진다.

스크린샷 2023-04-08 오후 3.24.01

@Temporal

  • 날짜 타입(java.util.Date, java.util.Calendar)을 매핑할 때 사용
  • 참조: LocalDate, LocalDateTime을 사용할 때는 생략 가능(최신 하이버네이트 지원)
    • Hibernate가 알아서 timestamp date 등 처리해줌
1
2
3
4
5
6
7
8
@Temporal(TemporalType.TIMESTAMP)
private Date createdDate;
@Temporal(TemporalType.TIMESTAMP)
private Date lastModifiedDate;

private LocalDate testLocalDate;

private LocalDateTime testLocalDateTiem;

스크린샷 2023-04-08 오후 3.33.36

@Lob

  • 데이터베이스 BLOB, CLOB 타입과 매핑

    • @Lob에는 지정할 수 있는 속성이 없다

    • 매핑하는 필드 타입이 문자면 CLOB 매핑, 나머지는 BLOB 매핑

      • *CLOB: String, char[], java.sql.CLOB *
      • BLOB: byte[], java.sql. BLOB

기본키 매핑

기본 키 매핑 에너테이션

  • @Id (직접할당)

  • @GeneratedValue (자동생성)

    • IDENTITY: 데이터베이스에 위임, MYSQL

    • SEQUENCE: 데이터베이스 시퀀스 오브젝트 사용, ORACLE

      • @SequenceGenerator 필요
    • TABLE: 키 생성용 테이블 사용, 모든 DB에서 사용

      • @TableGenerator 필요
    • AUTO: 방언에 따라 자동 지정, 기본값

IDENTITY 전략 특징(!!!)

1
@GeneratedValue(strategy = GenerationType.IDENTITY)
  • 기본 키 생성을 데이터베이스에 위임

  • 주로 MySQL, PostgreSQL, SQL Server, DB2에서 사용
 (예: MySQL의 AUTO_ INCREMENT)

  • JPA는 보통 트랜잭션 커밋 시점에 INSERT SQL 실행

  • AUTO_ INCREMENT는 데이터베이스에 INSERT SQL을 실행

    한 이후에 ID 값을 알 수 있음

  • 주의 단점!!!! IDENTITY 전략은 em.persist() 시점에 즉시 INSERT SQL 실행 하고 DB에서 식별자를 조회

  • 이 전략만 유일하게 Em.persist() 한 시점에서 바로 insert쿼리가 날라가고, 바로 id값을 영속성 컨텍스트에 기록한다!!!

SEQUENCE 전략 특징

1
2
3
4
5
6
7
8
9
@Entity
@SequenceGenerator(
name = “MEMBER_SEQ_GENERATOR",
sequenceName = “MEMBER_SEQ", //매핑할 데이터베이스 시퀀스 이름
initialValue = 1, allocationSize = 1)
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE,
private Long id;
  • 데이터베이스 시퀀스는 유일한 값을 순서대로 생성하는 특별한 데이터베이스 오브젝트(예: 오라클 시퀀스)
  • *Em.persist() 하기 이전 먼저 pk에 해당하는 값을 알기위해(call next value for member_seq) Db에 접근하여, 영속성 컨텍스트에 pk값 갖은 상태로 저장 *
  • 추후 트랜잭션 커밋이 일어날때, SQL문 + 쓰기 지연들이 일어나면서 insert쿼리 날라감
  • 성능최적화를 위해 allocationSize=50를 통해 em.persist()를 할때마다, 다음 pk값의 50개를 한번에 배정받은후 애플리케이션 메모리에 기억후 사용함.

스크린샷 2023-04-09 오후 2.15.03

TABLE 전략

  • 키 생성 전용 테이블을 하나 만들어서 데이터베이스 시퀀스를 흉 내내는 전략
    • 장점: 모든 데이터베이스에 적용 가능
    • 단점: 성능
  • 운영에서 한 테이블 의존하기때문에 쓰기 쉽지않다.

권장하는 식별자 전략

  • 기본 키 제약 조건: null 아님, 유일, 변하면 안된다**.**
  • 미래까지 이 조건을 만족하는 자연키는 찾기 어렵다. 대리키(대체키)를 사용하자.
    (운영상 언젠가는 겹치거나, 쓰면안되는 정보들이 너무 많다. 따라서 의미없는 pk를 식별자로 하는게 좋다)
  • 예를 들어 주민등록번호도 기본 키로 적절하기 않다.
  • 권장**: Long형** + 대체키 + 키 생성전략 사용
  • uuid같은,

실전예제1

스크린샷 2023-04-09 오후 4.30.20

스크린샷 2023-04-09 오후 3.51.06

이런 설계의 문제점은 바로 RDB에 맞게 객체설계를 가져간다는 느낌이다.

왜냐하면, Order 객체를 찾아온후 .getMemberId()를 한후, 다시 이 ID값으로 Member table에서 getMember를 해야하기때문

전혀 객체 지향적이지 않음.

객체지향적인 설계는 이를 order.getMember() 를 통해 바로 객체를 탐색할수있어야함

데이터 중심 설계의 문제점

  • 현재 방식은 객체 설계를 테이블 설계에 맞춘 방식
  • 테이블의 외래키를 객체에 그대로 가져옴
  • 객체 그래프 탐색이 불가능
  • 참조가 없으므로 UML도 잘못됨
CATALOG
  1. 1. 엔티티 매핑
    1. 1.1. 엔티티 매핑 소개
    2. 1.2. @Entity
    3. 1.3. @Table
    4. 1.4. 데이터베이스 스키마 자동 생성
      1. 1.4.1. 데이터 베이스 스키마 자동 생성 - 속성
      2. 1.4.2. 데이터베이스 스키마 자동 생성 주의!!!
    5. 1.5. DDL 생성 기능
  2. 2. 필드와 컬럼 매핑
    1. 2.1. 요구사항 추가
    2. 2.2. 매핑 에너테이션 정리
    3. 2.3. @Colum
    4. 2.4. @Enumerated
    5. 2.5. @Temporal
      1. 2.5.0.1.
  3. 2.6. @Lob
  • 3. 기본키 매핑
    1. 3.1. 기본 키 매핑 에너테이션
      1. 3.1.1. IDENTITY 전략 특징(!!!)
      2. 3.1.2. SEQUENCE 전략 특징
      3. 3.1.3. TABLE 전략
    2. 3.2. 권장하는 식별자 전략
  • 4. 실전예제1
    1. 4.1. 데이터 중심 설계의 문제점