- 객체와 테이블 매핑: @Entity, @Table
- 기본 키 매핑: @Id
- 필드와 컬럼 매핑: @Column
- 연관관계 매핑: @ManyToOne, @JoinColumn
@Entity
속성 | 기능 | 기본값 |
name | JPA에서 사용할 Entity 이름을 지정. 설정하지 않으면 Class명을 그대로 사용한다 | (ex) User class -> "User") |
@Entity 사용시 주의사항
- 기본 생성자는 필수 (파라미터가 없는 public 혹은 protected)
=> 실제로 Entity Class에서 생성자를 생략해도 Java에서는 기본생성자를 만들어주기 때문에 오류가 발생하지는 않음.
=> JPA가 객체 생성시에 기본 생성자를 사용하기 때문
- final, enum, interface, inner Class에서는 사용할 수 없음
- 저장할 필드에 final 키워드를 사용하면 안됨
@Table
: Entity와 매핑할 테이블을 지정한다
속성 | 기능 | 기본값 |
name | 매핑할 테이블명 | Entity Name |
catalog | catalog 기능이 있는 데이터베이스에서 catalog를 매핑 | |
schema | schema 기능이 있는 데이터베이스에서 schema를 매핑 | |
uniqueConstraints (DDL) | DDL 생성시에 unique 제약조건을 만든다. 2개 이상의 복합 unique 제약조건도 생성가능. - 이 기능은 스키마 자동 생성 기능을 사용해서 DDL을 만들때만 사용 (그러나 이방법은 비추천) |
@Id
기본키 할당. JPA에서 데이터를 제어할 식별자에 해당한다. 보통 테이블의 기본키(PK)에 매핑해주는 경우가 많다
- 키(key)생성 전략
1] 직접생성
ex) user.setId(1);
@Id 적용가능 자바타입
- 자바 기본형 (char, int, long, double 등...)
- 자바 Wrapper형 (Integer, Long, Double 등...)
- String
- java.util.Date, java.sql.Date
- java.math.BigDecimal, java.math.BigInteger
=> 보통은 직접 할당보다는 자동생성 할당전략으로 많이 사용한다.
2] 자동생성
- AUTO(default): JPA 구현체(스프링부트에서는 Hibernate)가 생성 방식을 결정(JPA에게 위임한다)
=> Hibernate 5.0 부터는 기본 전략이 TABLE, 그이전에는 IDENTITY 방식이다
- IDENTITY: 사용하는 데이터베이스가 키 생성을 결정(= 데이터베이스에 위임)한다. MySQL이나 MariaDB는 기본기 자동생성 Auto-Increment 방식을 사용한다
=> 식별자 생성 전략은 엔티티가 데이터베이스에 저장되어야 식별자를 구분할 수 있으므로, 트랜잭션을 지원하는 쓰기 지연이 동작하지 않음 (데이터 저장후 식별자에 할당)
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import javax.persistence.*;
@Getter
@Setter
@Entity
@Table(name = "user")
public class UserEntity {
@Id
@Column(name="user_id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long userId;
private String userName;
private Integer userAge;
}
- SEQUENCE: 데이터베이스의 sequence를 이용해서 key를 생성한다. @SequenceGenerator와 함께 사용
=> 시퀸스 생성기를 통해 식별자가 만들어지므로, 식별자 할당후 데이터를 저장)
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import javax.persistence.*;
@Getter
@Setter
@Entity
@SequenceGenerator(
name = "user_seq_generator",
sequenceName = "user_seq",
initialValue = 1, allocationSize = 50
)
@Table(name = "user")
public class UserEntity {
@Id
@Column(name="user_id")
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "user_seq_generator")
// @SequenceGenerator는 여기에 놓아도 됨
private Long userId;
private String userName;
private Integer userAge;
}
@SequenceGenerator 속성
속성 | 기능 | 기본값 |
name | 식별자 생성기 이름 | required |
sequenceName | 데이터베이스에 등록되어 있는 시퀸스 이름 | hibernate_sequence |
initialValue | DDL 생성시에만 사용됨. 시퀸스 DDL을 생성할 때 처음 시작하는 수를 지정 | 1 |
allocationSize | 시퀸스 한번 호출에 증가하는 수 (?) default가 50인이유 => 식별자를 구하기 위해 시퀸스를 조회할 때 DB를 호출한다. 만약 가져오는 수치가 1이라면, 1씩 증가할떄마다 DB를 호출하고, 50이라면 1~50까지 미리 가져와서 메모리에 할당시켜두고 쓰다가, 50까지 다 사용하면 그때 DB를 호출한다. SEQUENCE 성능 최적화와 관련된다 |
50 |
- TABLE: 키 생성 전용 테이블을 생성하여 키생성. @TableGenerator와 함께 사용
SEQUENCE 테이블을 생성해야한다.
CRATE TABLE user_sequence_table (
seq_name varchar(255) NOT NULL,
next_val BIGINT,
PRIMARY KEY (seq_name)
);
/*
테이블 데이터
컬럼명 seq_name | next_val
user_seq | 3
member_seq | 121
product_seq | 211
*/
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import javax.persistence.*;
@Getter
@Setter
@Entity
@TableGenerator(
name = "user_table_seq_generator",
table = "user_sequence_table", // 키생성 테이블명
pkColumnName = "seq_name" // 시퀸스 컬럼명
pkColumnValue = "user_seq", // 키로 사용할 값 이름
valueColumnName = "next_val" // 시퀸스 값 컬럼명
allocationSize = 1
)
@Table(name = "user")
public class UserEntity {
@Id
@Column(name="user_id")
@GeneratedValue(strategy = GenerationType.TABLE, generator = "user_table_seq_generator")
private Long userId;
private String userName;
private Integer userAge;
}
@TableGenerator 속성
속성 | 기능 | 기본값 |
name | 식별자 생성기 이름 | required |
table | 키생성 테이블명 | hibernate_sequences |
pkColumnName | 시퀸스 컬럼명 | sequence_name |
valueColumnName | 시퀸스 값 컬럼명 | next_val |
pkColumnValue | 키로 사용할 값 이름 | 엔티티 이름 |
initialValue | 초기 값, 마지막으로 생성된 값이 기준 | 0 |
allocationSize | 시퀸스 한번 호출에 증가하는 수 => SEQUENCE전략과 마찬가지로 최적화와 관련이 있다. (DB 통신 횟수) |
50 |
usiqueConstraints(DDL) | DDL 생성시에 unique 제약조건을 만든다. 2개 이상의 복합 unique 제약조건도 생성가능. - 이 기능은 스키마 자동 생성 기능을 사용해서 DDL을 만들때만 사용 (그러나 이방법은 비추천) |
컬럼
@Column: 컬럼을 매핑한다.
- name: 필드와 매핑할 테이블의 컬럼명
@Enumerated: 자바의 enum 타입을 매핑한다
- value
EnumType.ORDINAL(default): enum 순서를 데이터베이스에 저장
EnumType.STRING: enum 이름을 데이터베이스에 저장
ex)
public enum STATUS {
READY, START, END
} // enum 정의
----
@Enumerated(EnumType.ORDINAL)
private STATUS status; // 어노테이션 정의
user.setStatus(STATUS.READY); -> 0으로 저장
----
@Enumerated(EnumType.STRING)
user.setStatus(STATUS.READY) -> "READY" 문자열이 저장
@Temporal: 날짜 타입을 매핑한다 (java.util.Date, java.util.Calendar)
- value
TemporalType.DATE: 날짜, 데이터베이스 date 타입과 매핑
TemporalType.TIME: 시간, 데이터베이스 time 타입과 매핑
TemporalType.TIMESTAMP: 날짜와 시간, 데이터베이스 timestamp 타입과 매핑
@Lob: BLOB(byte[], java.sql.BLOB), CLOB(String, char[], java.sql.CLOB) 타입을 매핑한다
@Transient: 특정 필드를 데이터베이스에 매핑하지 않는다
데이터베이스에 저장하지도않고 조회도 하지 않는다. 객체에 임시로 어떤 값을 보관하고 싶을 때 사용
@Access: JPA가 엔티티에 접근하는 방식을 지정한다
AccessType.FIELD: 필드에 직접 접근가능 (private라도 접근이 가능)
AccessType.PROPERTY: 접근자 Getter를 사용
@Entity
public class MyName {
@Id
private String id;
@Transient
priate String firstName;
@Transient
private String lastName;
@Access(AccessType.PROPERTY)
public String getFullName() {
return firstName + lastName;
}
}
참고자료
- https://jojoldu.tistory.com/295
- 서적 - 자바 ORM 표준 JPA 프로그래밍 제 4장 - 김영한 지음
'SpringFramework > JPA' 카테고리의 다른 글
JPA - 값타입 (0) | 2021.11.16 |
---|---|
JPA - 연관관계 고급매핑 (0) | 2021.11.15 |
JPA - 연관관계 (0) | 2021.11.14 |
JPA - 영속성 컨텍스트 (0) | 2021.11.03 |
JPA - 기본 개념 및 내용정리 (0) | 2021.02.05 |