4. 엔티티 매핑


JPA에서 지원하는 매핑 어노테이션은 다음과 같이 크게 4가지로 분류할 수 있음

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

1. @Entity

JPA를 사용해서 테이블과 매핑할 클래스는 @Entity 어노테이션을 필수로 붙여야 함

속성기능기본값
nameJPA에서 사용할 엔티티 이름을 지정한다. 보통 기본값인 클래스 이름을 사용한다. 만약 다른 패키지에 이름이 같은 엔티티 클래스가 있다면 이름을 지정해서 충돌하지 않도록 해야 한다.설정하지 않으면 클래스 이름을 그대로 사용(e.g. Member
  • 기본 생성자를 필수로 만들어줘야 한다 (public 또는 protected)
    JPA가 엔티티 객체를 생성할 때 기본 생성자를 사용함..
  • final 클래스, enum, interface, inner 클래스에는 사용할 수 없다
  • 저장할 필드에 final을 사용하면 안 된다.

2. @Table

엔티티와 매핑할 테이블 이름을 지정한다. 생략하면 매핑한 엔티티 이름을 테이블 이름으로 사용한다.

속성기능기본값
name매핑할 테이블 이름엔티티 이름
catalogcatalog 기능이 있는 데이터베이스에서 catalog를 매핑한다 
schemaschema 기능이 있는 데이터베이스에서 schema를 매핑한다 
uniqueConstraints
(DDL)
DDL 생성 시에 유니크 제약조건을 만든다.
2개 이상의 복합 유니크 제약조건도 만들 수 있다.
스키마 자동 생성 기능을 사용해서 DDL을 만들 때만 사용된다.
 
  • 1

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

JPA는 데이터베이스 스키마를 자동 생성하는 기능을 지원한다. 클래스의 매핑 정보를 보고 데이터베이스 방언을 이용해서 자동으로 데이터베이스 스키마를 생성해준다.

  • persistence.xml 설정 추가
    • <property name="hibernate.hbm2ddl.auto" value="create" />
      
    • 위 설정이 있으면 애플리케이션 실행 시점에 데이터베이스 테이블을 자동으로 생성
    • 기존 테이블이 있으면 drop 후 다시 생성
    • 운영 환경에서 사용할 만큼 완벽하진 않으니까 참고 용도로만 사용할 것을 권장

4. DDL 생성 기능

  • 어노테이션을 통해 제약조건을 추가하는 DDL을 정의할 수 있음
  • @column(name = "NAME", nullable = false, length = 10)
    private String username;
    


  • 유니크 제약조건
    • @Table의 uniqueConstraints 속성
    • @Table(name = "MEMBER", uniqueConstraints = {@UniqueConstraint(
        name = "NAME_AGE_UNIQUE",
        columnNames = {"NAME", "AGE"} )})
      public class Member {
        ...
      }
      
    • 위와 같이 제약조건을 추가하면 아래와 같은 DDL 생성됨
    • ALTER TABLE MEMBER
        ADD CONSTRAINT NAME_AGE_UNIQUE  UNIQUE (NAME, AGE)
      

5. 기본 키 매핑

@Id 어노테이션을 이용해서 애플리케이션에서 직접 기본 키를 할당하는 방법 외에 데이터베이스가 생성해주는 값을 기본 키로 하고싶을 때 어떻게하나?

5.1 기본 키 직접 할당 전략

@Id 어노테이션으로 직접 매핑하고, 엔티티 객체를 생성할 때 개발자가 직접 키를 넣어주는 방식

  @Id
  @Column(name = "id")
  private String id;

  ...
  
  Member member = new Member();
  member.setId("id1"); // 기본 키 직접 할당
  em.persist(member);
  • 다음 자바 타입들만 @Id 어노테이션 기본 키로 사용이 가능함
    • 자바 기본형
    • 자바 래퍼(wrapper) 형
    • String
    • java.util.Date
    • java.sql.Date
    • java.math.BigDecimal
    • java.math.BigInteger

5.2 IDENTITY 전략

  • 기본 키 생성을 데이터베이스에 위임하는 전략, 주로 MySQL, PostgreSQL, SQL Server, DB2에서 사용(e.g. MySQL AUTO_INCREMENT)
  • MySQL의 AUTO_INCREMENT를 기본 키로 사용했을 때 처럼 데이터베이스에 저장 후에 값을 알 수 있을 때 사용하는 전략
  • @GeneratedValue 어노테이션 사용
  • @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    ...
    
    Member member = new Member();
    em.persist(member);
    
    System.out.println("id : " + member.getId()); // 1 출력
    
  • IDENTITY 전략과 최적화
    • 키 값을 데이터베이스에 저장 후 알 수 있으므로, 키 값을 가져오기 위해 추가로 조회하게 됨
    • JDBC3에서 추가된 Statement.getGeneratedKeys()를 상요하면 저장과 동시에 생성된 기본 키도 받아올 수 있음
    • hibernate도 이러한 방식으로 최적화 되어있음
    • 또한, 저장을 해야 키 값을 알 수 있기 때문에 em.persist() 호출과 동시에 쓰기 지연을 하지 않고 바로 INSERT SQL을 쿼리함

5.3 SEQUENCE 전략

  • 데이터베이스 시퀀스 : 유일한 값을 순서대로 생성하는 특별한 데이터베이스 오브젝트
  • SEQUENCE 전략은 이 시퀀스를 사용해서 기본 키를 생성하는 것
  • 시퀀스를 지원하는 오라클, PostgreSQL, DB2, H2 데이터베이스에서 사용 가능
  • IDENTITY 전략과 다른점?
    • SEQUENCE 전략은 em.persist()를 호출할 때 먼저 데이터베이스 시퀀스를 사용해서 식별자를 조회
    • 조회한 식별자를 엔티티에 할당한 후에 영속성 컨텍스트에 엔티티 저장
    • 트랜잭션 커밋 시 플러시 할 때 데이터베이스에 저장함
  CREATE TABLE BOARD (
    ID BIGINT NOT NULL PRIMARY KEY,
    DATA VARCHAR(255)
  )
  // 시퀀스 생성
  CREATE SEQUENCE BOARD_SEQ START WITH 1 INCREMENT BY 1;
  • 위 코드와 같이 SQEUNCE를 생성해주고 아래와 같이 시퀀스를 매핑해서 사용
  @Entity
  @SequenceGenerator(
    name = "BOARD_SEQ_GENERATOR",
    sequenceName = "BOARD_SEQ", // 매핑할 데이터베이스 시퀀스 이름
    initialValue = 1, allocationSize = 1
  )

  public class Board {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE,
                    generator = "BOARD_SEQ_GENERATOR")
    private Long id;
  }
  • @SequenceGenerator : 시퀀스 생성기(“BOARD_SEQ_GENERATOR”) 등록
속성기능기본값
name식별자 생성기 이름필수
sequenceName데이터베이스에 등록되어 있는 시퀀스 이름hibernate_
sequence
initialValueDDL 생성 시에만 사용됨. 시퀀스 DDL을 생성할 처음 시작 수 지정1
allocationSize시퀀스 한 번 호출에 증가하는 수(성능 최적화에 사용)50
catalog,
schema
데이터베이스 catalog, schema 이름 

5.4 Table 전략

  • 키 생성 전용 테이블을 하나 만들고 여기에 이름과 값으로 사용할 컬럼을 만들어 데이터베이스 시퀀스를 흉내내는 전략
  • 테이블을 사용하기 때문에 모든 데이터베이스에 적용이 가능함
    create table MY_SEQUENCES (
      sequence_name varchar(255) not null,
      next_val bigint,
      primary key ( sequence_name )
    )
    
  • 키 생성기를 사용할 때 마다 next_val이 증가함

5.5 Auto 전략

  • 데이터베이스에서 지원하는 전략을 고려해서 자동으로 선택해주는 전략
  • 오라클은 SEQUENCE, MySQL은 IDENTITY 선택
  • @Entity
    public class Board{
      @Id
      //@GeneratedValue(strategy = GenerationType.AUTO)
      @GeneratedValue // strategy의 기본 값이 AUTO라서 그냥 이렇게만 적어도 됨
      private Long id;
    }
    
  • 데이터베이스 변경 시에도 코드 수정이 필요 없음
  • AUTO 사용 시 SEQUENCE나 TABLE 전략이 선택되면 시퀀스나 키 생성 테이블을 미리 만들어 둬야 함
    • 스키마 자동 생성 기능을 사용하면 하이버네이트가 기본값으로 적절히 생성해줌

기본 키 매핑 정리

  • 직접 할당 : em.persist() 호출 전에 애플리케이션에 직접 식별자를 할당
  • SEQUENCE : 데이터베이스 시퀀스에서 식별자 값 획득 후 영속성 컨텍스트에 저장
  • TABLE : 데이터베이스 시퀀스 생성용 테이블에서 식별자 값 획득 후 영속성 컨텍스트에 저장
  • IDENTITY : 데이터베이스에 엔티티를 저장해서 식별자 값을 획득 후 영속성 컨텍스트에 저장

6. @Enumeration

속성기능기본값
value- EnumType.ORDINAL : enum 순서를 데이터베이스에 저장
- EnumTypes.String : enum 이름을 데이터베이스 저장
EnumType.Ordinal

Ordinal 쓰면 망함.. 중간에 EnumType을 추가하게 될 경우 문제 발생


7. @Temporal

  • 날짜 타입(java.util.Date, java.util.Calendar)을 매핑할 때 사용
속성기능기본값
value- TemporalType.DATE : 날짜, 데이터베이스 date 타입과 매핑(예 : 2013-10-11)
- TemporalType.TIME : 시간, 데이터베이스 time 타입과 매핑(예 : 11:11:11)
- TemporalType.TIMESTAMP : 날짜와 시간, 데이터베이스 tiemstamp 타입과 매핑(예 : 2013-10-11 11:11:11)
필수 지정

8. @Lob

  • 데이터베이스 BLOB, CLOB 타입과 매핑한다
  • 필드가 문자면 CLOB, 나머지는 BLOB으로 매핑함

9. @Transient

  • 해당 필드는 매핑하지 않을 때 사용, 객체에 임시로 어떤 값을 보관할 때 사용
  •   @Transient
      private Integer tmp;
    

10. @Access

  • JPA가 엔티티 데이터에 접근하는 방식을 지정한다
    • 필드 접근 : AccessType.FIELD, 필드 접근 권한이 private이어도 직접 접근
    • 프로퍼티 접근 : AccessType.PROPERTY, 접근자(Getter, Setter)를 사용





© 2020.02. by blupine