[JPA] 4장 엔티티 매핑

off_sujin·2022년 2월 10일
0

본 글은 김영한님의 <자바 ORM 표준 JPA 프로그래밍>을 읽고 공부한 내용을 정리한 글입니다.

  1. @Entity
  2. @Table
  3. 데이터베이스 스키마 자동 생성
  4. DDL 생성 기능
  5. 기본 키 매핑
  6. 필드와 컬럼 매핑

1. @Entity

  • JPA를 사용해서 테이블과 매핑할 클래스에 붙인다.
  • name 속성을 설정하지 않으면 클래스 이름을 그대로 사용한다.
  • 주의사항
    • 기본 생성자는 필수
    • final, enum, interface, inner 클래스에 사용 불가
    • 저장 필드에 final 사용 불가

2. @Table

  • 엔티티와 매핑할 테이블을 지정한다.
  • name 속성을 설정하지 않으면 엔티티 이름을 그대로 사용한다.

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

  • 애플리케이션 실행 시점에 데이터베이스 테이블을 자동으로 생성한다.

    • persistence.xml 에 다음 속성 추가
      <property name="hibernate.hbm2dd1.auto" value="create" />
  • hibernate.hbm2ddl.auto 속성
    - create : drop + create
    - create-drop : drop + create + drop
    - update : 변경 사항만 수정
    - validate : 변경 사항이 있으면 경고를 남기고 실행하지 않는다.

    운영 서버에서 create, create-drop, update와 같이 DLL을 수정하는 옵션은 사용하지 말자.

  • 이름 매핑 전략 변경
    - 자바의 카멜 표기법 -> 데이터베이스의 언더스코어
    - @Column.name 속성으로 직접 바꾸기
    - 자동 매핑
    persistence.xml 에 다음 속성 추가
    <property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.ImproveNamingStrategy" />

4. DDL 생성 기능

  • 아래의 예제처럼 @Column 매핑 정보를 활용하여 자동으로 생성되는 DDL에 not null과 문자열 크기를 지정할 수 있다.
@Column(name = "NAME", nullable = false, length = 10)
private String name;
  • 이런 기능들은 단지 DDl을 자동 생성할 때만 사용되고 JPA의 실행 로직에는 영향을 주지 않는다.

5. 기본 키 매핑

직접 할당 : 기본 키를 애플리케이션에서 직접 할당
자동 생성 : 대리 키 사용
- IDENTITY : 기본 키 생성을 데이터베이스에 위임
- SEQUENCE : 데이터베이스 시퀀스 이용
- TABLE : 키 생성 테이블 사용

5.1 직접 할당

  • @Id로 매핑한다.
  • em.persist() 로 엔티티를 저장하기 전에 애플리케이션에서 직접 할당해야 한다.
Board board = new Board();
board.setId("1"); // id 직접 할당
em.persist(board);

5.2 IDENTITY

  • 기본 키 생성을 데이터베이스에 위임하는 전략이다.
  • MySQL, PostgreSQL, SQL Server, DB2에서 주로 사용한다.
  • @Id와 @GeneratedValue 애노테이션을 사용한다.
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
  • 트랜잭션을 지원하는 쓰기 지연이 동작하지 않는다.
    • IDENTITY 전략은 엔티티를 DB에 저장해야 식별자를 구할 수 있다.
    • 따라서 em.persist() 를 호출하는 즉시 INSERT SQL이 DB에 전달된다.
    • 데이터베이스에서 식별자를 조회한 뒤, 엔티티의 식별자에 할당한다.

5.3 SEQUENCE

  • 유일한 값을 순서대로 생성하는 데이터베이스 오브젝트를 이용한다.
  • 주로 오라클, PostgreSQL, DB2, H2에서 사용한다.
  • 트랜잭션을 지원하는 쓰기 지연 동작한다.
    • em.persist()` 를 호출할 때 데이터베이스 시퀀스에서 식별자를 조회한다.
    • 식별자를 엔티티에 할당한 후 영속성 컨텍스트에 저장한다.
    • 트랜잭션이 커밋되고 플러시가 일어나면 엔티티를 데이터베이스에 저장한다.

5.4 TABLE

  • 키 생성 전용 테이블을 만들어서 사용한다.
  • 시퀀스 대신 테이블을 사용하는 것을 제외하면 SEQUENCE 전략과 동일하다.

5.5 AUTO

  • 선택한 데이터베이스 방언에 따라 IDENTITY, SEQUENCE, TABLE 중 하나를 자동으로 선택한다.
  • 데이터베이스를 변경해도 코드를 수정할 필요가 없다는 장점이 있다.
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

<식별자 선택 전략>
1. null 값을 허용하지 않는다.
2. 유일해야 한다.
3. 변하지 않아야 한다.

6. 필드와 컬럼 매핑

6.1 @Column

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

  • @Column 생략

    • @Column 생략, 자바 기본 타입
      int data1; -> data1 integer not null
      null 값을 입력할 수 없다.

    • @Column 생략, 객체 타입
      Integer data2; -> data2 integer
      null 값을 입력할 수 있다.

    • @Column 사용, 자바 기본 타입
      @Column int data3; -> data3 integer
      @Column은 nullable = true 가 기본값이므로 null 값을 입력할 수 있다.
      따라서 nullable = false 로 지정해야 안전하다.

6.2 @Enumerated

  • 자바의 enum 타입을 매핑한다.

  • @Enumerated 의 속성

    • value : 기본값은 ORDINAL
      - EnumType.ORDINAL : enum 순서를 DB에 저장
      - EnumType.STRING : enum 이름을 DB에 저장

      enum의 순서가 바뀌거나 추가되는 상황을 대비하여 EnumType.STRING을 사용할 것을 권장한다.

6.3 @Temporal

  • 날짜 타입을 매핑한다.
  • @Temporal 의 속성
    • value : TemporalType은 필수로 지정
      • TemporalType.DATE : 데이터베이스 date 타입과 매핑
      • TemporalType.TIME : 데이터베이스 time 타입과 매핑
      • TemporalType.TIMESTAMP : 데이터베이스 timestamp 타입과 매핑

6.4 @Lob

  • 데이터베이스 BLOB, CLOB 타입과 매핑한다.
    • CLOB : String, char[], java.sql.CLOB
    • BLOB : byte[], java.sql.BLOB

6.5 @Transient

  • 해당 어노테이션을 가지면 매핑하지 않는다.
  • 객체에 임시로 어떤 값을 보관하고 싶을 때 사용한다.

6.6 @Access

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

  • 접근 방식

    • 필드 접근

      • AccessType.FIELD
      • 필드 접근 권한이 private이어도 접근할 수 있다.
    • 프로퍼티 접근

      • AccessType.PROPERTY
      • 접근자 Getter를 사용한다.
  • @Access를 설정하지 않으면 @Id의 위치를 기준으로 접근 방식을 설정한다.

    • @Id가 필드에 있으면 @Access(AccessType.FIELD)와 같다.
      @Id
      private String id;
    • @Id가 Getter에 있으면 @Access(AccessType.PROPERTY)와 같다.
      @Id
      public String getId() {
          return id;
      }
profile
학습 중..

0개의 댓글