직역하면 '실체', '독립체' 라는 뜻으로 업무에 필요하고 유용한 정보를 저장하고 관리하기 위한 '어떤 것(Thing)'이라고 말할 수 있다. (DB에 저장되거나 가져와지는 객체라고 생각하면 편할것 같습니다. )
일반적인 의미로는 하나의 요소를 다른 요소와 대응시키거나 연결하는 프로세스를 말합니다.
📌
Entity(객체)와 관계형 데이터베이스(테이블, 컬럼, 관계 등)를 Mapping 즉 서로 대응시켜 연결하는 과정으로 보통 어노테이션(Annotation)을 사용하여 이루어지며 Mapping을 통해 JPA는 객체와 데이터베이스 간의 변환을 자동으로 처리할 수 있게 됩니다.
구분 | 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-drop | create와 같으나 종료시점에 테이블 DROP |
update | 변경분만 반영 ALTER |
validate | 엔티티와 테이블이 정상 매핑되었는지만 확인 |
none | 사용하지 않음 |
📚 참고 및 자료 출처 : 자바 ORM 표준 JPA 프로그래밍 - 기본편 (김영한)