Jpa

엔티티 매핑

k0o9 2021. 1. 9. 16:07

참고 이글은 자바 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