엔티티 매핑
참고 이글은 자바 ORM 표준 JPA프로그래밍을 읽고 정리한 글입니다.
@Entity
-Jpa를 사용해서 테이블과 매핑할 클래스에 필수적으로 붙여야함.
-이 어노테이션이 붙은 클래스는 JPA가 관리하는 것으로 엔티티라고 한다.
-name속성을 지정해서 매칭할 테이블 이름을 지정할 수 있음. 미지정시 클래스이름을 사용.
-기본생성자 필수
-final,eum,interface,inner클래스에 사용 x
-저장할 필드에 final 사용 x
@Table
-엔티티와 매핑할 테이블을 지정하는 어노테이션. 생략하면 엔티티 이름을 클래스명으로 사용.
-마찬가지로 name속성으로 지정가능.
-catalog,schem 속성이 있으며 각각의 기능이 있는 db에서 각각의 기능 매핑.
기본키 매핑
이때까지는 @Id 어노테이션을 이용해서 회원의 기본키를 애플리케이션에서 직접 할당하였다. 그러나 Auto Increment처럼 DB에서 직접 할당해주는 값들은 어떻게 기본키로 사용해야 할까?
JPA에서 기본 키 생성 전략은 다음과 같다.
-직접할당:애플리케이션에서 직접 할당
-자동생성 : 대리키 사용 방식
1.IDENTITY : 기본 키 생성을 DB에 위임한다.
2.SEQUENCE: 데이터베이스 시퀸스를 사용해서 기본 키를 할당한다.
3.TABLE: 키 생성 테이블을 사용한다. -> 모든 DB에 사용가능
1,2번의 방식의 경우에는 DB 벤더마다 지원하는 방식이 다르기 때문에 사용할 수 있는 DB가 정해져 있는 반면 3번의 방식은 테이블을 활용하므로 모든 DB에서 사용이 가능하다.
기본 키 직접 할당 전략
@Id
@Column(name = "ID")
private String id;
위와 같이 @Id로 매핑을 하면 직접 할당이 된다. 기본 키 직접할당전략은 jpa에서 저장전에 애플리케이션에서 기본키에 직접 할당하는 방법.
-사용 가능한 자바타입
1.자바 기본형
2.자바 래퍼형
3.String
4.java.util.Date
5.java.sql.Date
6.java.math.BigDecimal
7.java.math.BigInteger
IDENTITY 전략
주로 MySQL,PostgreSQL,SQL Sever,DB2에서 사용. MySQL에 AUTO_INCREMENT를 사용한 것처럼 DB에 먼저 값이 저장하고 나서야 기본 키값을 구할 수 있다.
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private String id;
@Id 어노테이션 뿐만 아니라 @GeneratedValue(strategy = GenerationType.Type) 어노테이션에 type을 지정해줄 수 있다. 이 방법을 사용하면 JPA는 기본 키 값을 얻어오기 위해 DB를 한번 더 조회한다.
Sequence 전략
DB SEQUENCE는 유일한 값을 순서대로 생성하는 특별한 DB 오브젝트. 이 전략은 이러한 SEQUENCE를 사용하여 기본키를 생성한다. SEQUENCE를 지원하는 PostgreSQL,DB2,H2 데이테베이스에서 사용할 수 있다.
Entity
@Table(name="MEMBER")
@SequenceGenerator(name = "SEQ_NAME_GENERATOR",sequenceName ="SEQ_NAME",initialValue = 1,allocationSize = -1)
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE,generator = "SEQ_NAME_GENERATOR")
private String id;
사용한 것을 보니 먼저 @SequenceGenrator 를 사용한 SEQ_NAME_GENERATOR 생성기를 SEQ_NAME이라는 이름을 가진 DB테이블과 매핑하여 만들었다. 그리고 @GeneratedValue(strategy = GenerationType.SEQUENCE,generator = "SEQ_NAME_GENERATOR")를 통해 키 생성전략을 시퀸스로 설정하고 generator를 방금 만든 시퀸스 생성기로 선택했다. 따라서 id값을 이제 seq_name_generator가 할당한다.
이렇게 IDENTITY와 SEQUENCE를 보았는데 실제로 이들을 사용하면 코드가 동일 할 것이다. 그럼 머가 다르냐고 생각 할 수 있지만 이 둘의 내부 동작 방식이 다르다.
SEQUENCE : 조회 -> 할당 -> 저장
IDENTITY : 저장 -> 조회 ->할당
Table전략
키 생성 전용 테이블을 하나 만들고 여기에 이름과 값을 사용할 칼럼을 만들어 DV 시퀸스를 흉내내는 방법.
모든 DB에서 사용 가능.
다음과 같이 키생성 용도로 사용할 테이블을 만들고 @TableGenerator와 매핑하여 테이블 키 생성기를 등록한다.
@Table(name="MEMBER")
@TableGenerator(name="SEQ__NAME_GENERATOR",table = "MY_SEQUENCES",pkColumnValue ="SEQ_NAME",allocationSize = 1)
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.TABLE,generator = "SEQ_NAME_GENERATOR")
private String id;
SEQ_NAME_GENERATOR라는 이름의 테이블 키 생성기를 등록하고 키생성 용도로 만든 테이블과 매핑했다. 그리고 테이블 키 생성기를 사용하기 위해 GenerationType을 Table로 지정하고 generator로 만들어둔 키 생성기를 지정했다. 이제부터 id는 SEQ_NAME_GENERATOR 테이블 키 생성기가 할당한다.
테이블 전략 방식은 시퀸스 대신 테이블을 만들어 사용한다는 것만 제외하면 내부 동작방식이 똑같다.
Auto 전략
Auto전략은 이렇게 다양한 키 할당 전략을 데이터베이스 방언에 따라 알맞게 매핑해 주는 방법이다.
장점 : DB를 변경해도 코드를 수정할 필요가 없다.
단점 : SEQUENCE나 TABLE전략이 선택되면 시퀀스나 키 생성용 테이블을 미리 만들어 두어야한다.
필드와 컬럼 매핑
필드와 컬럼을 매핑하는 어노테이션
@Column : 컬럼을 매핑
@Enumerated : 자바의 enum타입을 매핑한다.
@Temporal : 날짜 타입을 매핑한다.
@Lob : BLOB,CLOB 타입을 매핑한다.
@Transient : 특정 필드를 데이터 베이스에 매핑하지 않는다.
@Column
객체 필드를 테이블 컬럼에 매핑한다.
속성
-name :필드와 매핑할 테이블의 컬럼이름
-insertable : 엔티티 저장시 같이 저장. false-> db에 저장안함
-updatable : 엔티티 수정시 같이 수정. flase -> db에 수정x
-table : 하나의 엔티티를 두개 이상의 테이블에 매핑할때 사용.
-nullable(DDL) :null값의 허용여부를 묻는다.
-unique(DDL) : 유니크 제약조건을 걸때 사용. 두개 이상의 제약조건일경우 @Table.uniqueConstraints를 사용해야 한다.
-length(DDL) : 문자 길이 제약조건 STRING일때만 사용.
-percision,scale(DDL) : BIGDECIMAL타입에서 사용. percision은 소수점을 포함한 전체 자릿수, scale은 소수의 자릿수.
insertable 옵션과 updatable옵션은 정보를 읽기만 하고 실수로 변경하는 것을 방지하고 싶을 때 사용.
@Enumerated
enum타입을 DB에 저장할때 사용.
속성
ORDINAL:Enum에 정의된 순서대로 0부터 값이 db에 저장
장점 :데이터베이스에 저장되는 데이터 크기가 작음.
단점 :이미 저장된 enum의 순서를 변경x
String:enum문자 그대로 db에 저장.
장점:저장된 enum의 순서가 바뀌거나 추가되도 안전.
단점:DB에 저장되는 크기가 ORDINAL에 비해서 크다.
Temporal
날짜 타입을 매핑할때 사용.
TemporalType.DATE:DB date타입과 매핑.
TemporalType.TIME :DB time타입과 매핑
TemporalType.TIMESTAMP:DB timestamp매핑.
@Lob
DB BLOB,CLOB타입과 매핑
문자면 CLOB, 나머지는 BLOB로 매핑.
@Transient
객체에 임시로 어떤 값을 보관하고 싶을때 사용. 저장도 조회도 하지않는다.
@Access
엔티티 데이터에 접근하는 방식을 지정.
-필드접근:AccessType.Field. 필드에 직접 접근. private여도 접근가능.
-프로퍼티 접근:AccessType.PROPERTY로 지정. 접근자를 사용한다. GETTER