기본 키 매핑
기본 키를 할당하는 방식은 두 가지입니다.
- 직접 할당
- 자동 할당
기본 키 직접 할당
기본키로 지정하고싶은 필드에 @Id를 붙여줍니다.
@Id
@Column(name = "ID")
private int id;
@Id 적용 가능 타입 :
- 자바 기본형
- Wrapper 타입
- String
- java.util.Date
- java.sql.Date
- java.math.BigDecimal
- java.math.BigInteger
@Id 필드에 개발자가 직접 값을 할당해야 합니다. 그런데 영속성 컨텍스트는 엔티티를 식별자값으로 관리하기 때문에 식별자 값이 할당되어야 영속성 컨텍스트의 관리를 받을 수 있습니다.
식별자 값이 없는 상태로 em.persist하면 예외가 발생하는데, 어떤 예외가 발생하는지는 jpa 표준에 정의되어있지 않습니다. 하이버네이트를 구현체로 사용하면 jpa 최상위 예외인 javax.persistence.PersistenceException예외가 발생하는데, 내부에 하이버네이트 예외인 org.hibernate.id.IdentifierGenerationException 예외를 포함하고 있습니다.
자동 할당 방식
기본 키 생성을 DB에 위임하는 전략인데, 데이터베이스 벤더마다 사용하는 전략이 다릅니다. @GeneratedValue로 전략을 지정해줍니다.
@Id
@Column(name = "ID")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
IDENTITY 전략
auto-increment로 기본 키 값을 자동으로 생성하는 DBMS(MySQL, PostgreSQL 등)에서 사용하는 전략입니다.
DB에 값을 저장할 때 ID컬럼을 비워두면 DB가 순서대로 값을 채워주는 방식입니다.
em.persist하려면 식별자가 있어야 하는데, 식별자가 채워지려면 DB에 엔티티가 저장되어야 합니다.
따라서 이 전략을 사용할 때 em.persist를 호출하면 가장 먼저 insert sql이 DB에 전달되어 엔티티가 저장됩니다.
따라서 이 전략은 쓰기 지연이 동작하지 않습니다.
참고로, identity 전략은 DB에 insert한 후에 식별자 값을 알 수 있으므로 JPA가 엔티티에 식별자값을 할당하려면 DB에 넣고 또 추가로 DB를 조회해야 합니다. jdbc3에 주가된 Statement.getGeneratedKeys()를 사용하면 데이터를 저장하는 동시에 생성된 기본키 값을 얻어올 수 있는데, 하이버네이트는 이 메서드를 사용해서 DB와 한 번만 통신합니다.
SEQUENCE 전략 ...
그 외에도 몇 가지 전략이 있는데 일단 MySQL을 사용할 예정이므로 MySQL에서 쓰이지 않는 개념은 넘어가겠습니다.
컬럼 매핑
@Column | 객체 필드를 테이블 컬럼과 매핑 name : 매핑할 테이블 컬럼의 이름 nullable : null허용 여부. false로 설정하면 DDL 생성 시 not null 제약조건 추가됨 unique : 한 컬럼에 간단히 유니크 제약조건을 걸 때 사용 length : String타입에만 사용, 문자 길이 제약조건 |
@Enumerated | 자바의 enum타입 매핑 EnumType.ORDINAL : enum 순서를 데이터베이스에 저장 EnumType.STRING : enum 이름을 데이터베이스에 저장 |
@Temporal | 날짜 타입 매핑 |
@Lob | BLOB, CLOP 타입 매핑 |
@Transient | 특정 필드를 데이터베이스에 매핑하지 않을 때 사용 |
@Access | JPA가 엔티티에 접근하는 방식 지정 |
@Column
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "posts_id")
private Long id;
@Column(name = "posts_title", length = 500, nullable = false) //테이블의 칼럼 (길이 500, null 불가능)
private String title;
@Column(name = "posts_content", columnDefinition = "TEXT", nullable = false)
private String content;
@OneToMany(mappedBy = "posts")
private List<Comment> comments;
이 어노테이션을 생략하면 nullable = true가 디폴트로 적용됩니다. 객체 타입 컬럼은 null값이 허용되므로 @Column을 생략하면 nullable = true가 그대로 적용되지만, 자바 기본형 컬럼에는 null값이 허용되지 않기 때문에 기본형에 이 어노테이션을 생략하면 jpa는 자동으로 not null 제약조건을 추가해줍니다.
따라서 자바 기본형 컬럼에 @Column을 사용한다면 nullable = false로 지정하는 것이 안전합니다.
@Enumerated
// enum 클래스
enum RoleType {
ADMIN, MEMBER
}
// User 엔티티 클래스의 RoleType 필드를 enum 이름으로 매핑
@Enumerated(value = EnumType.STRING)
private RoleType roleType;
// enum 사용 방법
user.setRoleType(RoleType.ADMIN); // 데이터베이스에 문자 ADMIN으로 저장
자바의 enum타입을 매핑할 때 사용하는 어노테이션입니다.
ORDINAL로 지정했다면, enum에 정의된 순서대로 ADMIN은 0, MEMBER가 1로 저장됩니다. 저장되는 데이터 크기가 STRING보다 작다는 점에서 좋지만 이미 저장된 enum의 순서는 변경할 수 없기 때문에, enum클래스에 정의된 내용이나 순서가 바뀌면 문제가 생기게 됩니다. 따라서 STRING을 사용하는 것이 더 안전합니다.
@Temporal
@Temporal(TemporalType.TIMESTAMP)
private Date createdDate;
@Temporal(TemporalType.TIMESTAMP)
private Date lastModifiedDate;
java.util.Date나 java.util.Calendar와 같이 날짜 타입을 매핑할 때 사용하는 어노테이션입니다.
TemporalType.DATE : 데이터베이스의 date타입과 매핑합니다. (2024-09-11)
TemporalType.TIME : 데이터베이스의 time타입과 매핑합니다. (10:11:11)
TemporalType.TIMESTAMP : 데이터베이스의 timestamp타입과 매핑합니다. (2024-09-11 10:11:11)
@Temporal을 생략하면 자바의 Date와 가장 유사한 timestamp로 정의됩니다.
'JPA' 카테고리의 다른 글
[JPA] 지연 로딩 (0) | 2024.09.12 |
---|---|
[JPA] 엔티티 매핑 / 데이터베이스 스키마 자동 생성 기능 (ddl-auto) (4) | 2024.09.11 |