자바 ORM 표준 JPA 프로그래밍 - 4장, 엔티티 매핑
자바 ORM 표준 JPA 프로그래밍에서 읽은 내용을 정리하는 글입니다😄
JPA에서 가장 중요한 일은 엔티티와 테이블을 정확히 매핑하는 것이다.
매핑하는데 필요한 어노테이션은 다음과 같다.
- 객체 ~ 테이블 : @Entity, @Table
- 기본키 : @Id
- 필드 ~ 컬럼 : @Column
- 연관관계 : @ManyToOne, @JoinColumn
4.1 @Entity
테이블과 매핑할 클래스에 반드시 @Entity 어노테이션을 붙여야 한다.
@Entity가 붙은 클래스를 엔티티라 부르며, JPA가 관리하게 된다.
속성으로는 name이 있고 이는 JPA에서 사용할 엔티티 이름을 의미한다.
기본값은 클래스 이름이 된다.
@Entity 사용 시 주의사항은 다음과 같다.
- 기본 생성자 반드시 사용
- final, enum, interface, inner 클래스에서 사용 불가
- 저장할 필드에 final 사용 불가
4.2 @Table
엔티티와 매핑할 테이블에는 @Table 어노테이션을 붙여야 한다.
속성들은 다음과 같다.
- name : 매핑할 테이블 이름
- catalog : catalog 기능이 있는 DB에서 catalog 매핑
- schema : schema 기능이 있는 DB에서 schema 매핑
- uniqueConstraints(DDL) : DDL 생성 시 유니크 제약조건 생성
4.3 데이터베이스 스키마 자동 생성
JPA는 데이터베이스 스키마를 자동 생성하는 기능을 지원한다.
사용 시 애플리케이션 실행 시점에 데이터베이스 테이블이 자동으로 생성되므로
개발자가 직접 생성하는 수고를 덜게 된다.
persistence.xml
에 다음 속성을 추가하면 된다.
<property name="hibernate.hbm2ddl.auto" value="create" />
hibernate.hbm2ddl.auto
의 속성들은 다음과 같다.
- create : 기존 테이블을 삭제 후 새로 생성
- create-drop : create 속성 + 애플리케이션 종료 시 생성한 DDL 제거
- uplast_modified_at : DB 테이블과 엔티티 매핑정보를 비교해 변경 사항만 수정
- valilast_modified_at : DB 테이블과 엔티티 매핑정보를 비교해 변경 사항 있으면 경고 남김 (DDL 수정X)
- none : 자동 생성 기능 사용X
4.4 DDL 생성 기능
회원 이름은 필수로 입력돼야 하며 10자를 초과하면 안된다는 제약조건을 추가하는 상황을
생각해보자. 다음 코드를 추가해주면 된다.
...
@Column(name = "NAME", nullable = false, length = 10) //추가 코드
private String username;
...
이렇게 수정하면 DDL에 not null과 문자 크기 10 제약조건을 추가할 수 있다.
이번엔 유니크 제약조건을 만들어주는 @Table의 uniqueConstraints 속성을 알아보자.
//유니크 제약조건
@Entity(name="Member")
@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)
위에서 설명한 기능들은 DDL 생성 시에만 사용되고 JPA 실행 로직에는 영향을 주지 않는다.
그러나 애플리케이션 개발자가 엔티티만 보고도 제약조건을 쉽게 파악할 수 있다는 장점이 있다.
4.5 기본 키 매핑
기본 키 직접 할당 전략
기본 키를 직접 할당하려면 @Id로 매핑하면 된다.
@Id
@Column(name = "id")
private String id;
em.persist()
로 엔티티 저장 전에 애플리케이션에서 기본 키를 직접 할당하는 방법이다.
Board board = new Board();
board.setId("id1"); //기본 키 직접 할당
em.persist(board);
IDENTITY 전략
기본 키 생성을 DB에 위임하는 전략으로, 주로 MySQL, PostgreSQL, SQL Server, DB2
에서 사용한다. @GenerateValue의 stratgy 속성 값을 GenerateType.IDENTITY
로 지정하자.
이 전략 사용 시 JPA는 기본 키 값을 얻기 위해 DB를 추가로 조회한다.
//IDENTITY 매핑 코드
@Entity
public class Board {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY) //추가 코드
private Long id;
...
}
//IDENTITY 사용 코드
Board board = new Board();
em.persist(board);
SEQUENCE 전략
DB 시퀀스는 유일한 값을 순서대로 생성하는 특별한 DB 오브젝트로, 이를 통해 기본 키
를 생성한다. 이 전략은 PostgreSQL, DB2, H2에서 사용할 수 있다.
//시퀀스 DDL
CREATE SEQUENCE BOARD_SEQ START WITH 1 INCREMENT BY 1;
//시퀀스 매핑 코드
@Entity
@SequenceGenerator(
name = "BOARD_SEQ_GENERATOR",
sequenceName = "BOARD_SEQ", //매핑 DB 시퀀스 이름
initialValue = 1,
allocationSize = 1
)
public class Board {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE,
generator = "BOARD_SEQ_GENERATOR")
private Long id;
...
}
시퀀스 사용 코드는 IDENTITY 사용 코드와 같지만 내부 동작이 다르다.
IDENTITY 전략은 엔티티를 DB에 저장 후 식별자를 조회해서 엔티티의 식별자에 할당한다.
SEQUENCE 전략은 em.persist()
호출 시 먼저 DB 시퀀스를 통해 식별자를 조회하고,
조회한 식별자를 엔티티에 할당 후 엔티티를 영속성 컨텍스트에 저장한다.
이후 트랜잭션을 커밋해 엔티티를 DB에 저장한다.
다음은 @SequenceGenerator
속성들이다.
name
: 식별자 생성기 이름sequenceName
: DB 시퀀스 이름initialValue
: DDL 생성 시 시작하는 숫자 지정 (DDL 생성 시에만 사용)allocationSize
: 시퀀스 한 번 호출에 증가하는 수 (성능 최적화용)catalog
,schema
: DB catalog, schema 이름
TABLE 전략
키 생성 전용 테이블을 만들고 이름과 값으로 사용할 컬럼을 만들어 DB 시퀀스를 흉내내는 전략이다.
이 전략은 앞에서 살펴본 전략과 달리 모든 DB에서 사용 가능하다.
TABLE 전략을 사용하려면 키 생성 용도로 사용할 테이블을 만들어야 한다.
//TABLE 전략 키 생성 DDL
create table MY_SEQUENCES (
sequence_name varchar(255) not null, //시퀀스 이름
next_val bigint, //시퀀스 값
primary key ( sequence_name )
)
@TableGenerator
를 사용해 테이블 키 생성기를 등록한다.
아래 예제에서는 BOARD_SEQ_GENERATOR라는 이름의 테이블 키 생성기를 등록하고,
위에서 생성한 MY_SEQUENCES 테이블을 키 생성용 테이블로 매핑한다.
TABLE 전략을 사용하기 위해 @GeneratedType.TABLE
을 선택하고,
@GeneratedValue.generator
에 방금 만든 테이블 키 생성기를 지정한다.
이제부터 id 식별자 값은 BOARD_SEQ_GENERATOR 테이블 키 생성기가 할당한다.
//TABLE 전략 매핑 코드
@Entity
@TableGenerator (
name = "BOARD_SEQ_GENERATOR",
table = "MY_SEQUENCES",
pkColumnValue = "BOARD_SEQ", allocationSize = 1)
)
public class Board {
@Id
@GeneratedValue(strategy = GenerationType.TABLE,
generator = "BOARD_SEQ_GENERATOR)
private Long id;
...
}
TABLE 전략 매핑 사용 코드는 이전에 살펴본 매핑 사용 코드와 같다.
내부 동작방식 또한 SEQUENCE 전략과 같다.
@TableGenerator
속성들은 다음과 같다.
name
: 식별자 생성기 이름table
: 키생성 테이블명pkColumnName
: 시퀀스 컬럼명valueColumnName
: 시퀀스 값 컬럼명pkColumnValue
: 키로 사용할 값 이름initialValue
,allocationSize
,catalog
,schema
,uniqueConstraints(DDL)
AUTO 전략
GenerationType.AUTO
는 선택한 DB 방언에 따라 IDENTITY, SEQUENCE, TABLE 전략 중 하나를 자동으로 선택한다.
가령, 오라클은 SEQUENCE를, MySQL은 IDENTITY를 사용한다.
//AUTO 전략 매핑 코드
@Entity
public class Board {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
...
}
@GeneratedValue.strategy
의 기본값은 AUTO이므로 @GeneratedValue
라 써도 결과가 같다.
AUTO 전략의 장점은 DB 변경 시에도 코드를 수정할 필요가 없다는 점이다.
따라서 키 생성 전략이 확정되지 않은 개발 초기 단계 혹은 프로토타입 개발 시 유용하다.
댓글남기기