프로젝트 git url | github.com/rtef23/JpaStudy |
필요 | 1. docker 2. docker-compose |
프로젝트 정보 | mysql : 5.7 - docker image java : 1.8 |
객체와 테이블 매핑
- @Entity
- 해당 annotation이 붙은 클래스는 JPA가 관리하는 엔티티
- 기본 생성자 필요(public, protected 생성자)
- final 클래스, enum, interface, inner 클래스에 사용 불가
- 저장할 필드에 final 사용 불가
- 속성
- name : JPA에서 사용할 엔티티 이름을 지정한다.
- 기본값 : 클래스의 SimpleName을 그대로 사용
- 다른 패키지에 동일한 클래스가 있는 경우, 별도의 name으로 지정하여 사용한다.
@Entity
public class Member {
...
}
- @Table
- 엔티티와 매핑할 테이블 지정
- catalog, scheme, uniqueConstraints 속성을 정의할 수 있다.
@Entity
@Table(name = "member")
public class Member {
...
}
데이터베이스 스키마 자동 생성
- DDL을 application 실행 시점에서 자동 생성
- 테이블 중심 => 객체 중심
- 데이터베이스 방언(Dialect)을 활용하여, 데이터베이스에 맞는 DDL 생성
- hibernate.hbm2ddl.auto 옵션을 활성화하여 사용
- create
- SessionFactory 시작시, 스키마를 삭제하고 다시 생성(Drop + Create)
- create-drop
- SessionFactory 종료시, 스키마를 삭제(Drop + Create + Drop)
- update
- SessionFactory 시작시, 객체 구성과 스키마를 비교하여 컬럼 추가 작업을 진행
- 기존 스키마를 삭제하지 않고 유지
- validate
- SessionFactory 시작시, 객체 구성과 스키마를 비교하여 다른 경우 예외를 발생
- create
//persistence.xml
<property name="hibernate.hbm2ddl.auto" value="create"/>
- @Column
- DDL 생성 시점에서 컬럼별 unique, 길이 제한과 같은 제약(unique, length, nullable, ...)을 줄 수 있다.
- 컬럼 매핑시 사용하는 annotation
- insertable
- insert시 해당 값을 데이터베이스에 같이 입력할지 여부
- updatable
- update시 해당 값을 데이터베이스에 같이 수정할지 여부
- nullable
- DDL 생성시 not null 제약 조건을 추가
- insert, update시 null체크도 하게 된다.
- length
- 값의 길이 제한
- columnDefinition
- 컬럼의 제약 사항을 줄 수 있음
@Entity
@Table("member")
class Member {
@Column(columnDefinition = "varchar(100) default 'TEST_VALUE'")
private String test1;
...
}
/* 아래와 같은 제약사항이 DDL 생성시 들어가게 된다.
create table member (
test1 varchar(100) default 'TEST_VALUE',
...
) engine=InnoDB
*/
- @Temporal
- 날짜 타입 매핑
- LocalDate, LocalDateTime의 타입의 경우, 해당 annotation을 사용할 필요가 없다.
- java.sql.Date, java.sql.Time, java.sql.Timestamp의 타입을 사용하는 경우 사용
- @Enumerated
- enum 타입 매핑
- EnumType으로 ORDINAL, STRING으로 넣을 수 있다.(기본 값으로는 ORDINAL로 설정되어 있다.)
- ORDINAL
- enum에서 해당 값의 index 값을 DB에 저장한다.
- enum 수정시 순서에 신경을 쓰며 수정을 해야하기 때문에 좋지 않다.
- DDL 생성시에도 컬럼 타입을 integer로 생성하게 된다.
- STRING
- enum에서 해당 값의 name()을 DB에 저장한다.
- DDL 생성시 컬럼 타입을 varchar로 생성하게 된다.
- ORDINAL
- @Lob
- BLOB, CLOB 매핑
- 매핑하는 타입이 문자의 경우, CLOB 매핑
- 매핑하는 타입이 문자가 아닌 경우, BLOB 매핑
- @Transient
- 주로 메모리상에서만 임시로 어떤 값을 보관하고 싶을 때 사용
- 데이터베이스 저장 X, 조회 X
기본 키 매핑
- 직접 할당
- @Id만 사용
- 자동 생성(@GeneratedValue)
- IDENTITY
- 기본키 생성 방법을 데이터베이스에 위임, MySQL에서 사용
- mysql의 auto_increment
- id를 임의의 값으로 수정하면 안된다.
- 데이터베이스에 insert SQL을 실행한 이후에 ID 값을 알 수 있음
- GenerationType.IDENTITY의 경우, EntityManager.commit() API를 호출하는 시점에 insert 쿼리를
전송하는 것이 아니라 EntityManager.persist() API를 호출하는 시점에 insert 쿼리를 전송한다.
- SEQUENCE
- 데이터베이스 시퀀스 오브젝트 사용, Oracle에서 사용
- @SequenceGenerator 필요
- GenerationType.SEQUENCE의 경우, EntityManager.persist() API를 호출하는 시점에서는 DB로 부터 sequence 값을 조회하는 쿼리가 전송된다.
- TABLE
- 키 생성용 테이블 사용, 모든 DB에서 사용
- DB 내부의 트랜잭션을 잡기 때문에 조심해서 사용해야 할듯 함.
- IDENTITY
/* @GeneratedValue(strategy = GenerationType.AUTO)의 insert 실행시 아래의 쿼리들이 전송된다.
Hibernate:
select
next_val as id_val
from
hibernate_sequence for update
Hibernate:
update
hibernate_sequence
set
next_val= ?
where
next_val=?
Hibernate:
into
test
(name, id)
values
(?, ?)
*/
- AUTO
- 방언에 따라 자동 지정
- hibernate5.4.27 기준 MySQL의 경우, 별도의 sequence 테이블을 생성하는 것이 기본 옵션
- AUTO
- 권장하는 식별자 전략
- 기본 키 제약 조건
- null 아님
- 유일
- 불변
- 기본 키 제약 조건
- @SequenceGenerator
- allocationSize의 기본 값은 50으로 설정되어 있다.
- initialValue, allocationSize을 이용하여 기본키 할당 성능 향상 방법
- allocationSize 만큼을 DB에서 미리 올려두어서 해당 서버에서는 allocationSize 범위 내에서는 다시 네트워크를 타지 않고 메모리에서 범위 내 값 안에서 증가하도록 하는 방법
- 여러 컴포넌트(ex. tomcat)가 있는 경우 각자의 initialValue를 다르게 주면 될 듯
- WAS가 꺼지게 되는 경우 중간에 ID로 할당받지 않은 빈 sequence가 존재할 듯
@Entity
@Table(name = "test")
@SequenceGenerator(name = "testSequenceGenerator", sequenceName = "TEST_SEQ", initialValue = 1, allocationSize = 100)
public class Test {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "testSequenceGenerator")
private Long id;
...
}
//====총 100번의 persist API 호출====
/*
최초 persist API 실행시에만 sequence select & update 쿼리가 2번 호출 되었고
나머지 호출 실행시에는 sequence select & update 쿼리가 호출되지 않는다.
*/
IntStream.rangeClosed(0, 99)
.forEach((number) -> {
Test test = new Test();
test.setName("test-" + number);
entityManager.persist(test);
});
/*==== sequence select & update 쿼리====
Hibernate:
select
next_val as id_val
from
TEST_SEQ for update
Hibernate:
update
TEST_SEQ
set
next_val= ?
where
next_val=?
*/
- @TableGenerator
- table에도 auto_increment와 같은 값을 allocationSize 만큼 올려두어 SequenceGenerator와 같이 사용할 수 있다.
'JPA' 카테고리의 다른 글
[JPA] 8. 연관관계 매핑 - 다대일(N : 1) (0) | 2021.01.10 |
---|---|
[JPA] 7. 연관관계 (0) | 2021.01.06 |
[JPA] 5. 영속성 컨텍스트 - 2 (0) | 2020.12.31 |
[JPA] 4. 영속성 컨텍스트 - 1 (0) | 2020.12.31 |
[JPA] 3. JPA 기본 api 사용 (0) | 2020.12.30 |