[ 국비학원수료! 근데 JPA를 안 배웠네? ] JPA 가장 중요한 2가지 - 엔티티 매핑

JYS·2024년 1월 4일
0
post-thumbnail

🤔 엔티티 매핑?

Entity

직역하면 '실체', '독립체' 라는 뜻으로 업무에 필요하고 유용한 정보를 저장하고 관리하기 위한 '어떤 것(Thing)'이라고 말할 수 있다. (DB에 저장되거나 가져와지는 객체라고 생각하면 편할것 같습니다. )

Mapping

일반적인 의미로는 하나의 요소를 다른 요소와 대응시키거나 연결하는 프로세스를 말합니다.

📌
Entity(객체)와 관계형 데이터베이스(테이블, 컬럼, 관계 등)를 Mapping 즉 서로 대응시켜 연결하는 과정으로 보통 어노테이션(Annotation)을 사용하여 이루어지며 Mapping을 통해 JPA는 객체와 데이터베이스 간의 변환을 자동으로 처리할 수 있게 됩니다.


✔ Mapping

구분Annotation
객체와 테이블 매핑@Entity, @Table
필드와 컬럼 매핑@Column
기본 키 매핑@Id
날짜 타입 매핑@Temporal
enum 타입 매핑@Enumerated
BLOB, CLOB 매핑@Lob
특정 필드를 컬럼에 매핑하지 않음@Transient
@Entity
public class Member {
    @Id
    private Long id;

    @Column(name="name")
    private String username;

    private Integer age;

    @Enumerated(EnumType.STRING)
    private RoleType roleType;

    private LocalDate test1
    private LocalDateTime test2

    @Lob
    private String description;
    
    @Transient
    private int temp;

}

@Entity : JPA가 관리하는 엔티티 표시 ( 기본 생성자 필수 )
@Table : 엔티티와 매핑할 테이블 지정 name 속성을 통해 매핑할 테이블 이름을 지정할 수 있다.
@Column

옵션설명
name필드와 매핑할 테이블의 컬럼 이름
insertable, updateable등록, 변경 가능 여부
nullable(DDL)null값의 허용 여부를 설정한다. false로 설정하면 DDL 생성 시에 not null 제약조건이 붙는다.
nuique(DDL)@Table의 uniqueConstraints와 같지만 한 컬럼에 간단히 유니크 제약조건을 걸 때 사용한다.
columnDefinition(DDL)데이터베이스 컬럼 정보를 직접 줄 수 있다
length(DDL)문자 길이 제약조건, String 타입에만 사용한다.
precision, scale(DDL)BigDecimal 타입에서 사용한다(BigInteger도 사용할 수 있다) precision은 소수점을 포함한 전체 자리수를, scale은 소수의 자릿수 (double, float타입에는 적용되지 않는다. 아주 큰 숫자나 정밀한 소수를 다루어야 할 때만 사용한다.

@Enumerated : 자바 enum타입을 매핑할 때 사용 ( EnumType.STRING 사용! )
EnumType.ORDINAL - enum 순서를 데이터베이스에 저장
EnumType.STRING - enum 이름을 데이터베이스에 저장
@Temporal : LocalDate, LocalDateTime으로 대신 사용 (최신 하이버네이트 지원)
@Lob : 지정할 수 있는 속성이 없고, 문자면 CLOB 나머지는 BLOB 매핑
@Transient : 데이터베이스에 저장x, 조회x 주로 메모리상에서만 임시로 어떤 값을 보관하고 싶을 때 사용


✔ 기본키 매핑

@Entity
@SequenceGenerator(
        name = "MBR_SEQ_GENERATOR",
        sequenceName = "MBR_SEQ", //매핑할 데이터베이스 시퀀스 이름
        initialValue = 1, allocationSize = 1 )
public class Member {
    @Id
    //@GeneratedValue(strategy = GenerationType.IDENTITY)
    @GeneratedValue(strategy = GenerationType.SEQUENCE,
            generator = "MBR_SEQ_GENERATOR")
    private Long id;

    @Column(name = "name", nullable = false)
    private String username;

    public Member() {

    }
}

직접 할당 : @Id
자동 생성 : @GeneratedValue

strategy설명
IDENTITY테이터베이스에 위임, MYSQL
SEQUENCE데이터베이스 시퀀스 오브젝트 사용, ORACLE ( @SequenceGenerator필요 )
TABLE키 생성용 테이블 사용, 모든 DB에서 사용 ( @TableGenerator필요 )
AUTO방언에 따라 자동 지정, 기본값

📌
IDENTITY전략은 id값(PK)을 세팅하지 않고 DB에 넣어야한다 즉 null로 SQL요청을 하면 DB에서 그때 id값을 세팅한다
id값을 알려면 DB에 insert되어진 후에 알 수 있다.
하지만 JPA의 영속성 컨텍스트에서 관리되려면 PK값을 알아야한다 그렇기 때문에 예외적으로 EntityManager.persist 하는 시점에 바로 SQL문이 요청되어지고 insert된 id값을 영속성 컨텍스트에 바로 저장하게된다.

SEQUENCE전략 특징
sequence도 IDENTITY전략과 마찬가지로 영속성 컨텍스트에서 관리할 id값을 알아야 하기 때문에 persist하는 시점에 시퀀스의 값을 불러와(call) 영속성 컨텍스트에 저장하고 관리하게 된다.

💡 그렇다면 insert쿼리를 한번 보낼일을 id값을 받아오는 요청, insert하는 요청 이렇게 2번의 요청을 하게되는데 네트워크를 왔다 갔다 하는 비용이 성능상 좋지 않다 라는 생각을 할 수 있다.

@Entity
@SequenceGenerator(
        name = "MBR_SEQ_GENERATOR",
        sequenceName = "MBR_SEQ",
        initialValue = 1, allocationSize = 50 ) //allocationSize default = 50
public class Member {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE,
            generator = "MBR_SEQ_GENERATOR")
    private Long id;
    }

이런 성능상의 문제를 해결하기 위해 allocationSize속성을 사용할 수 있다.
allocationSize는 한번 호출할때 증가하는 값으로 ( default 50 )
처음 호출할때 50만큼 DB를 증가시켜놓고 50을 받아와 메모리 상에서는 1씩 사용하는 전략이다.
이렇게되면 시퀀스가 50을 초과하기 전까지는 DB에 next val 요청을 보내지 않기 때문에 네트워크 비용을 줄일 수 있다.


✔ 데이터베이스 스키마 자동 생성

애플리케이션 로딩시점에 DB테이블을 생성(DDL)하는 기능( 로컬이나 테스트에만 사용권장 )

 <property name="hibernate.hbm2ddl.auto" value="create" />
옵션설명
create기존테이블 삭제 후 다시 생성 (DROP+CREATE)
create-dropcreate와 같으나 종료시점에 테이블 DROP
update변경분만 반영 ALTER
validate엔티티와 테이블이 정상 매핑되었는지만 확인
none사용하지 않음

📚 참고 및 자료 출처 : 자바 ORM 표준 JPA 프로그래밍 - 기본편 (김영한)

profile
go

0개의 댓글