엔티티 매핑

Sangkyeong Lee·2021년 5월 19일

[인프런]JPA

목록 보기
3/8

인프런 강의 < 자바 ORM 표준 JPA 프로그래밍 - 기본편 > 정리


시작

JPA를 사용하는데 가장 중요한일은 엔티티와 테이블을 정확히 매핑하는 것이므로 매핑 어노테이션을 숙지해야한다.

JPA가 지원하는 매핑 어노테이션에는 총 아래와 같이 4가지로 분류된다.

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

@Entity

JPA를 사용해서 테이블과 매핑할 클래스에 꼭 붙여야 한다.

@Entity 속성

속성기능기본값
nameJPA에서 사용할 엔티티 이름을 지정하며 보통 클래스 이름을 사용한다.설정하지 않으면 클래스 이름을 그대로 사용

@Entity 적용 시 주의할점

  • 기본 생성자는 필수
    • 자바는 생성자가 없으면 디폴트 생성자를 알아서 생성하지만 이미 생성자를 선언했을 경우 사용자가 직접 디폴트 생성자를 생성해야 한다!
      public Member(){} // 직접 선언
      public Member(String name) {this.name = name;} // 이미 선언되어있는 생성자
  • final 클래스, enum, interface, inner 클래스에는 적용할 수 없다.
  • 저장할 필드에 final을 사용하면 안된다.

@Table

@Table은 엔티티와 매핑할 테이블을 지정하며 생략시 매핑한 엔티티 이름을 테이블 이름으로 사용한다.

@Table 속성

속성기능기본값
name매핑할 테이블 이름엔티티 이름 사용
catalogcatalog 기능이 있는 db에서 catalog를 매핑한다
schemaschema 기능이 있는 db에서 schema를 매핑한다
DDL 생성 시, 유니크 제약조건을 만든다. 이 기능은 스키마 자동 생성 기능을 사용해서 DDL을 만들때만 사용

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

JPA는 데이터베이스 스키마를 자동으로 생성하는 기능을 지원한다.


클래스의 매핑정보를 보면 어떤 테이블의 어떤 컬럼을 사용하는지 알 수 있으므로 JPA는 매핑정보와 데이터베이스 방언을 사용해 스키마를 생성한다.

애플리케이션 실행 시점에 데이터베이스 테이블을 자동으로 생성하기 위해서
<property name="hibernate.hbm2ddl.auto" value="create" /> 속성을 추가하면 된다.

스키마 자동생성 기능을 사용하면 애플리케이션 실행 시점에 데이터베이스 테이블을 자동으로 생성하므로 개발자의 수고를 덜 수 있다.


하지만 DDL(Data Definition Language)은 완벽하지 않으므로 운영 환경 말고, 개발 환경에서 사용하거나 매핑을 어떻게 해야하는지 참고용으로 사용하는 것이 좋다.

hibernate.hbm2ddl.auto 속성

옵션설명
create기존 테이블을 삭제하고 새로 생성. DROP/CREATE
create-dropcreate 속성에 추가로 삭제. DROP/CREATE/DROP
update데이터베이스 테이블과 엔티티 매핑정보를 비교해서 변경사항 수정
validate데이터베이스 테이블과 엔티티 매핑정보를 비교해서 차이가 있으면 경고를 보낸다. 애플리케이션을 실행하지 않고 DDL을 수정하지 않는다.
none자동 생성 기능을 사용하지 않으려면 hibernate.hbm2ddl.auto속성을 삭제하거나 none으로 해주면 된다.
  • 운영장비에는 create, create-drop, update 사용 금지
  • 개발 초기 단계 create, update
  • 테스트 서버 update, validate
  • 스테이징, 운영 서버 validate, none

필드와 컬럼 매핑

분류매핑 어노테이션설명
@Column컬럼 매핑
@Enumerated자바의 enum타입 매핑
@Temporal날짜 타입 매핑
@LobBLOB, CLOB 타입 매핑
@Transient특정 필드를 데이터베이스에 매핑하지 않는다.
기타@AccessJPA가 엔티티에 접근하는 방식 지정

@Column

@Column은 객체 필드를 테이블 컬럼에 매핑한다. @Column속성중에 name, nullable외에는 거의 사용되지 않는다.

속성기능기본값
name필드와 매핑할 테이블의 컬럼 이름객체의 필드 이름
insertable엔티티 저장 시, 이 필드도 같이 저장한다. false로 설정하면 이 필드는 db에 저장하지 않는다true
updatable엔티티 수정 시, 이 필드도 같이 수정한다. false로 설정하면 db에 수정하지 않는다.true
table하나의 엔티티를 두 개 이상의 테이블에 매핑할 떄 사용한다. 지정한 필드를 다른 테이블에 매핑 가능현재 클래스가 매핑된 테이블
nullable(DDL)null값의 허용 여부 설정, false면 not null 제약붙음true
unique(DDL)한 컬럼에 간단히 유니크 제약조건 걸때 사용
columnDefinition데이터베이스 컬럼 정보를 직접 줄 수 있다.필드의 자바 타입과 방언 정보를 사용해서 적절한 컬럼 타입을 생성한다.
length(DDL)문자 길이 제약조건, String 타입에만 사용255
precision, scale(DDL)BigDecimal 타입에서 사용한다.(BigInteger도 사용가능), precision은 소수점을 포함한 전체 자릿수를, scale은 소수의 자릿수다(double, float타입에는 적용되지 않는다.)precision=19, scale=2

@Enumerated

속성기능기본값
value1. EnumType.ORDINAL: enum 순서를 데이터베이스에 저장

2. EnumType.STRING: enum 이름을 데이터베이스에 저장
EnumType.ORDINAL
enum RoleType {
    ADMIN, USER
}
  • ORDINAL 사용하지 말고 STRING 사용
    • ADMIN(0번), USER(1번) 사이에 enum에 한개가 추가돼서 new가 1번이 되고 USER가 2번이 된다. 하지만 기존 db에는 여전히 1번으로 남아 있기 때문에 사용 X

EnumType.ORDINAL은 enum에 정의된 순서대로 ADMIN은 0, USRE는 1 값이 데이터베이스에 저장된다

  • 장점: 데이터베이스에 저장되는 데이터 크기가 작다.
  • 단점: 이미 저장된 enum의 순서를 변경할 수 없다.

EnumType.STRING은 enum 이름 그대로 ADMIN은 'ADMIN', USER는 'USER'라는 문자로 데이터베이스에 저장된다.

  • 장점: 저장된 enum의 순서가 바뀌거나 enum이 추가되어도 안전하다.
  • 단점: 데이터베이스에 저장되는 데이터 크기가 ORDINAL에 비해서 크다.

@Temporal

날짜 타입(java.util.Date, java.util.Calendar)을 매핑할때 사용한다.

속성기능기본값
value1. TemporalType.DATE: 날짜, 데이터베이스 date 타입과 매핑

2. TemporalType.TIME: 시간, 데이터베이스 time 타입과 매핑

3. TemporalType.TIMESTAMP: 날짜와 시간, 데이터베이스 timestamp 타입과 매핑/TemporalType은 필수로 지정 해야함

@Temporal을 생략하면 자바의 Date와 가장 유사한 timestamp로 정의 된다.

@Lob

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


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

@Tansient

객체이 임시로 어떤 값을 보관하고 싶을 떄 사용

@Access

JPA가 엔티티 데이터ㅔ 접근하는 방식을 지정

  • 필드 접근: AccessType.FILED로 지정하며 필드에 직접 접근한다
  • 프로퍼티 접근: AccessType.PROPERTY로 지정하며 접근자 Getter를 사용한다.

    @Access를 설정하지 않으면 @Id의 위치를 기준으로 접근 방식 설정

기본 키 매핑

직접 할당: 기본 키를 애플리케이션에서 직접 할당한다.
자동 생성: 대리 키 사용 방식

  • IDENTITY: 기본 키 생성을 데이터베이스에 위임한다.
  • SEQUENCE: 데이터베이스 시퀀스를 사용해서 기본 키를 할당한다.
  • TABLE: 키 생성 테이블을 사용한다.

자동 생성 전략이 다양한 이유는 데이터베이스 벤더마다 지원하는 방식이 다르기 때문(ex. 오라클은 시퀀스 제공하지만 mysql은 제공하지 않고 기본 키 값을 자동으로 채워주는 AUTO_INCREMENT 기능제공)

직접 할당

직접할당을 하려면 @Id를 매핑하면 된다.

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

결론

기본 키 직접 할당은 persist()로 엔티티를 저장하기 전에 애플리케이션에서 기본 키를 직접 할당하는 방법

Board board = new Board();
board.setId("id1") // 기본 키 직접할당
em.persist(board);

IDENTITY 전략

IDENTITY는 기본 키 생성을 데이터베이스 위임하는 전략이다.

CREATE TABLE BOARD (
    ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    DATA VARCHAR(255)
);

INSERT INTO BOARD(DATA) VALUES('A');
INSERT INTO BOARD(DATA) VALUES('B');

AUTO_INCRMENT를 추가해서 데이터베이스 값을 저장할때 ID 컬럼을 비워두면 데이터베이스가 순서대로 값을 채워준다.

사용방법은 @GeneratedValue 어노테이션을 사용하고 strategy = GEnerationType.IDENTITY를 사용하면 된다.

IDENTITY 전략은 데이터를 데이터베이스에 INSERT한 후에 기본 키 값을 조회할 수 있다.


따라서 엔티티에 식별자 값을 할당하려면 JPA는 추가로 데이터베이스를 조회해야 한다.


또한 데이터베이스를 저장해야 식별자를 구할 수 있으므로, em.persist()를 호출하는 즉시 INSERT SQL이 데이터베이스에 전달된다.


따라서 이 전략은 트랜잭션을 지원하는 쓰기 지연이 동작하지 않는다.

SEQUENCE 전략

데이터베이스 시퀀스는 유일한 값을 생성하는 특별한 데이터베이스 오브젝트

@Entity
@SequenceGenerator(
    name = “MEMBER_SEQ_GENERATOR",
    sequenceName = “MEMBER_SEQ", //매핑할 데이터베이스 시퀀스 이름
    initialValue = 1, allocationSize = 1)
public class Member {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE,
        generator = "MEMBER_SEQ_GENERATOR")
    private Long id; 

@SequenceGenerator

속성설명기본값
name식별자 생성기 이름필수
sequenceName데이터베이스에 등록되어 있는 시퀀스 이름hibernate_sequence
initialValueDDL생성 시 사용됨. 시퀀스 DDL을 생성할 때 처음 시작하는 수를 지정1
allocationSize시퀀스 한 번 호출에 증가하는 수50
catalog, schema데이터베이스 catalog, schema 이름

TABLE 전략

키 생성 전용 테이블을 하나 만들어서 데이터베이스 시퀀스를 흉내내는 전략

  • 장점: 모든 데이터베이스에 적용 가능
  • 단점: 성능
create table MY_SEQUENCES (
    sequence_name varchar(255) not null,
    next_val bigint,
    primary key ( sequence_name )
)

@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; 
}

권장하는 식별자 전략

기본 키 제약 조건: null 아님, 유일, 변하면 안됨


주민등록번호 같은 것은 기본 키로 적절하지 않음 -> 자연키보단 대체키 사용

  • 권장: Long형 + 대체키 + 키 생성전략 사용

< 자료 출처: 자바 ORM 표준 JPA 프로그래밍 - 기본편 >

profile
💻Backend Developer

0개의 댓글