기본 키 매핑
기본 키를 할당하는 방식은 두 가지입니다.
- 직접 할당
- 자동 할당
기본 키 직접 할당
기본키로 지정하고싶은 필드에 @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로 정의됩니다.
'DB' 카테고리의 다른 글
| [DB/Error] h2 사용 에러 - engine[*]=InnoDB"; expected "identifier";] (1) | 2025.02.03 |
|---|---|
| [DB/테스트] @DataJpaTest (0) | 2025.02.03 |
| [DB/MySQL] MySQL Index의 동작 원리 - B-Tree 구조 (0) | 2025.02.03 |
| [DB/JPA] 엔티티 매핑(@Entity) / 데이터베이스 스키마 자동 생성 기능 (ddl-auto) (0) | 2024.12.16 |