객체와 테이블 매핑: @Entity, @Table
기본 키 매핑: @Id
필드와 컬럼 매핑: @Column
연관관계 매핑: @ManyToOne, @JoinColumn
🎈 4.1 @Entity
JPA를 사용해서 테이블과 매핑할 클래스는 @Entity 어노테이션을 필수로 붙여야 함.
- 기본 생성자 필수(파라미터가 없는 publici 또는 protected 생성자).
- final 클래스, enum, interface, inner 클래스에는 사용할 수 없음.
- 저장할 필드에 final을 사용하면 안 됨.
🎈 4.2 @Table
: 엔티티와 매핑할 테이블을 지정함. 생략하면 매핑한 엔티티 이름을 테이블 이름으로 사용함.
🎈 4.3 다양한 매핑 사용
import javax.persistence.*;
import java.util.Date;
@Entity
@Table(name="MEMBER")
public class Member {
@Id
@Column(name = "ID")
private String id;
@Column(name = "NAME")
private String username;
private Integer age;
//==추가==
@Enumerated(EnumType.STRING)
private RoleType roleType;
@Temporal(TemporalType.TIMESTAMP)
private Date createdDate;
@Temporal(TemporalType.TIMESTAMP)
private Date lastModifiedDate;
@Lob
private String description;
//Getter, Setter
...
}
public enum RoleType{
ADMIN, USER
}
🎈 4.4 데이터베이스 스키마 자동 생성
JPA는 데이터베이스 스키마를 자동으로 생성하는 기능을 지원함.
persistence.xml에 <property name="hibernate.hbm2ddl.auto" value="create" /> 를 추가하면 애플리케이션 실행 시점에 데이터베이스 테이블을 자동으로 생성함.
create: 기존 테이블 삭제하고 새로 생성
create-drop: create 속성에 추가로 앱 종료할 때 생성한 DDL을 제거함
update: 데이터베이스 테이블과 엔티티 매핑정보를 비교해서 변경 사항만 수정함.
validate: 데베 테이블과 엔티티 매핑정보 비교해서 차이가 있으면 경고 남기고 앱 실행하지 않음. DDL을 수정하지 않음.
none: 자동 생성 기능을 사용하지 않으려면 hibernate.hbm2ddl.auto 속성을 삭제하거나 유효하지 않은 옵션 값을 주면 됨. none은 유효하지 않은 옵션 값.
🎈 4.5 DDL 생성 기능
@Column(name = "NAME", nullable=false, length=10)
생성된 DDL
create table MEMBER {
ID varchar(255) not null,
NAME varchar(10) not null,
...
primary key(ID)
}
@Table(name="MEMBER", uniqueContraints = {@UniqueConstraint( name = "NAME_AGE_UNIQUE", columnNames = {"NAME", "AGE"} ) } )
생성된 DDL
ALTER TABLE MEMBER
ADD CONSTRAINT NAME_AGE_UNIQUE UNIQUE (NAME, AGE)
이런 기능들은 DDL을 자동 생성할 때만 사용되고 JPA의 실행 로직에는 영향을 주지 않음. 스키마 자동 생성 기능을 사용하지 않고 직접 DDL을 만든다면 사용할 이유 없음.
개발자가 엔티티만 보고 다양한 제약 조건 파악할 수 있다는 장점.
🎈 4.6 기본 키 매핑
직접 할당: 기본 키를 애플리케이션에서 직접 할당.
자동 생성: 대리 키 사용 방식
4.6.1 기본 키 직접 할당 전략
@Id
@Column(name = "id")
private String id;
@Id 적용 가능 타입
- 자바 기본형
- 자바 래퍼(Wrapper)형
- String
- java.util.Date
- java.sql.Date
- java.math.BigDecimal
- java.math.BigInteger
엔티티 저장하기 전에 애플리케이션에서 기본 키 직접 할당하는 방식
Board board = new Board();
board.setId("id1"); //기본 키 직접 할당
em.persist(board);
4.6.2 IDENTITY 전략
: 기본 키 생성을 데베에 위임하는 전략.
예를 들어 MySQL의 AUTO_INCREMENT 기능처럼
데베에 값을 저장하고 나서야 기본 키 값을 구할 수 있을 때 사용함.
@GeneratedValue(strategy = GenerationType.IDENTITY) 어노테이션으로 사용함. 이걸 사용하면 JPA는 기본 키 값을 얻어오기 위해 데베를 추가로 조회함.
엔티티가 영속 상태가 되려면 식별자가 반드시 필요한데 IDENTITY 식별자 생성 전략은 엔티티를 데베에 저장해야 식별자를 구할 수 있으므로 em.persist()를 호출하는 즉시 INSERT SQL이 데베에 전달됨.
따라서 트랜잭션을 지원하는 쓰기 지연이 동작하지 않는 전략임.
4.6.3 SEQUENCE 전략
데이터베이스 시퀀스: 유일한 값을 순서대로 생성하는 특별한 데이터베이스 오브젝트.
SEQUENCE 전략은 이 시퀀스 오브젝트를 사용해서 기본 키를 생성함. 시퀀스를 지원하는 데베에서만 사용 가능.
@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;
...
}
em.persist() 호출할 때 먼저 데베 시퀀스 사용해서 식별자 조회한 후에 조회한 식별자를 엔티티에 할당한 후에 엔티티를 영속성 컨텍스트에 저장. 이후 트랜잭션을 커밋해서 플러시 일어나면 엔티티를 데베에 저장함.
4.6.4 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;
...
}
시퀀스 대신에 테이블을 사용한다는 것만 제외하면 SEQUENCE 전략과 내부 동작방식이 같음.
4.6.5 AUTO 전략
데이터베이스 방언에 따라 IDENTITY, SEQUENCE, TABLE 전략 중 하나를 자동으로 선택함. 오라클을 선택하면 SEQUENCE, MySQL을 선택하면 IDENTITY를 사용함.
자연 키(주민등록번호, 이메일, 전화번호) 보다는 대리 키(오라클 시퀀스, auto_increment, 키생성 테이블 사용)를 권장한다.
🎈 4.7 필드와 컬럼 매핑: 레퍼런스
4.7.1 @Column
속성들
- name: 필드와 매핑할 테이블의 컬럼 이름
- nullable: null 값의 허용 여부를 설정.
insertable, updatable: 데베에 저장되어 있는 정보 읽기만 하고, 변경 방지하고 싶을 때
이외에도 table, nullable(DDL), unique(DDL), columnDefinition(DDL), length(DDL), precision, scale(DDL) 속성이 존재.
4.7.2 @Enumerated
enum RoleType{
ADMIN, USER
}
- EnumType.ORDINAL은 enum에 정의된 순서대로 ADMIN은 0, USER는 1 값이 데베에 저장됨
장점: 데베에 저장되는 데이터 크기가 작음
단점: 이미 저장된 enum의 순서를 변경할 수 없음
- EnumType.STRING은 enum 이름 그대로 'ADMIN', 'USER'라는 문자로 데베에 저장됨.
장점: 저장된 enum의 순서가 바뀌거나 enum이 추가되어도 안전함.
단점: 데베에 저장되는 데이터 크기가 ordinal보다 큼.
4.7.3 @Temporal
날짜 타입 매핑할 때 사용.
@Temporal(TemporalType.DATE)
private Date date; //날짜
@Temporal(TemporalType.TIME)
private Date time; //시간
@Temporal(TemporalType.TIMESTAMP)
private Date timestamp; //날짜와 시간
4.7.4 @Lob
매핑하는 필드 타입이 문자면 CLOB으로 매핑하고 나머지는 BLOB으로 매핑함.
CLOB: String, char[], java.sql.CLOB
BLOB: byte[], java.sql.BLOB
4.7.5 @Transient
매핑하지 않음. 객체에 임시로 어떤 값을 보관하고 싶을 때.
4.7.6 @Access
JPA가 엔티티 데이터에 접근하는 방식을 지정.
- 필드 접근: AccessType.FIELD로 지정. 필드에 직접 접근. 필드 접근 권한이 private이어도 접근할 수 있음.
- 프로퍼티 접근: AccessType.PROPERTY로 지정. 접근자(Getter)를 사용함.
@Access를 설정하지 않으면 @Id의 위치를 기준으로 접근 방식이 설정됨.
'JPA' 카테고리의 다른 글
[자바 ORM 표준 JPA 프로그래밍] 8장 프록시와 연관관계 관리 (0) | 2023.06.18 |
---|---|
[자바 ORM 표준 JPA 프로그래밍] 6장 다양한 연관관계 매핑 (0) | 2023.06.18 |
[자바 ORM 표준 JPA 프로그래밍] 5장 연관관계 매핑 기초 (0) | 2023.06.18 |
[자바 ORM 표준 JPA 프로그래밍] 3장 영속성 관리 (0) | 2023.06.04 |
[자바 ORM 표준 JPA 프로그래밍] 2장 JPA 시작 (0) | 2023.06.04 |