플러시 (flush)
영속성 컨텍스트의 변경내용을 데이터베이스에 반영
• 변경 감지
• 수정된 엔티티 쓰기 지연 SQL 저장소에 등록
• 쓰기 지연 SQL 저장소의 쿼리를 데이터베이스에 전송 (등록, 수정, 삭제 쿼리)
영속성 컨텍스트를 플러시하는 방법
• em.flush() - 직접 호출
• 트랜잭션 커밋 - 플러시 자동 호출
• JPQL 쿼리 실행 - 플러시 자동 호출
*플러시를 해도 1차 캐시는 유지된다. 1차 캐시는 엔티티 매니저, 즉 트랜잭션 단위이다.
*persist를 호출했을 때 DB에 데이터가 바로 저장되는 것이 아닌데, 플러시 호출 전에 JPQL로 데이터를 조회하려고 하면 DB에 존재하지 않는 데이터를 참조하려고 할 수 있다. 그런 상황을 방지하고자 JPQL 쿼리 실행시 플러시가 호출된다.
플러시 모드 옵션
• FlushModeType.AUTO: 커밋이나 쿼리를 실행할 때 플러시 (기본값)
• FlushModeType.COMMIT: 커밋할 때만 플러시. 보통은 큰 이점이 없기 때문에 AUTO로 쓰자.
플러시는!
• 영속성 컨텍스트를 비우지 않음
• 영속성 컨텍스트의 변경내용을 데이터베이스에 동기화
• 트랜잭션이라는 작업 단위가 중요 -> 커밋 직전에만 동기화 하면 됨
준영속 상태
영속 상태: 엔티티가 1차 캐시에 올라온 상태. em.persist, em.find 등
준영속 상태: 영속 상태의 엔티티가 영속성 컨텍스트에서 분리(detached). 영속성 컨텍스트가 제공하는 기능을 사용 못함

em.find 메서드에 의해 엔티티를 조회하는 쿼리 O = select query O
setName을 통한 데이터 변경 감지 (dirty check) X = update query X
=> 트랜잭션 커밋 전 해당 엔티티가 준영속 상태가 되었기 때문에
준영속 상태로 만드는 방법
• em.detach(entity): 특정 엔티티만 준영속 상태로 전환. 1차 캐시 내 특정 엔티티를 지움.
• em.clear(): 영속성 컨텍스트를 완전히 초기화. 1차 캐시를 비움
• em.close(): 영속성 컨텍스트를 종료
*데이터베이스에 저장된 엔티티에는 영향 없음.
*준영속 상태의 엔티티를 조회하면 다시 DB에 쿼리를 해서 1차 캐시에 저장하여 영속상태가 된다.
*사실상 1차 캐시가 영속성 컨텍스트
04. 엔티티 매핑
엔티티 매핑 소개
• 객체와 테이블 매핑: @Entity, @Table
• 필드와 컬럼 매핑: @Column
• 기본 키 매핑: @Id
• 연관관계 매핑: @ManyToOne, @JoinColumn
객체와 테이블 매핑
@Entity
• @Entity가 붙은 클래스는 JPA가 관리, 엔티티라 한다.
• JPA를 사용해서 테이블과 매핑할 클래스는 @Entity 필수
< 주의 >
• 기본 생성자 필수(파라미터가 없는 public 또는 protected 생성자) *reflection, proxing 등에 필요
• final 클래스, enum, interface, inner 클래스 사용X
• 저장할 필드에 final 사용 X
속성
• name
- JPA에서 사용할 엔티티 이름을 지정한다.
- 기본값: 클래스 이름을 그대로 사용(예: Member)
- 동일한 클래스 이름이 없으면 가급적 기본값을 사용한다.
@Table
• @Table은 엔티티와 매핑할 테이블 지정
속성
• name: 매핑할 테이블 이름 (기본값: 엔티티 이름)
• catalog: 데이터베이스 catalog 매핑
• schema: 데이터베이스 schema 매핑
• uniqueConstraints(DDL): DDL 생성 시에 유니크 제약 조건 생성
※ 데이터베이스 스키마 자동 생성
개발 장비에서만 사용
엔티티 객체 매핑을 해두면 애플리케이션 실행 시점에 테이블을 자동으로 생성한다.
데이터베이스 방언(같은 기능, 다른 명령어)을 활용해서 데이터베이스에 맞는 적절한 DDL을 생성한다.
<property name="hibernate.hbm2ddl.auto" value="create" />
속성(value)
• create: 기존테이블 삭제 후 다시 생성 (DROP + CREATE)
• create-drop: create와 같으나 종료시점에 테이블 DROP
• update: 변경분만 반영. DROP이 아닌 ALTER. 추가와 수정만 가능. 삭제는 불가
• validate: 엔티티와 테이블이 정상 매핑되었는지만 확인
• none: 사용하지 않음. 실제는 없는 옵션으로, 해당 옵션이 없기 때문에 실행이 안되는 것과 같은 결과.
* 주의 *
• 운영 장비에는 절대 create, create-drop, update 사용하면 안된다.
• 개발 초기 단계는 create 또는 update
• 테스트 서버(다수 개발자가 사용)는 update 또는 validate
• 스테이징과 운영 서버는 validate 또는 none
*로컬에서는 자유롭게 사용하나, 테스트 서버부터는 가급적 사용하지 않는 것이 좋다.
UPDATE를 사용하더라도, ALTER TABLE 이 되는 동안 데이터베이스가 lock이 걸려서 서비스가 멈출 수 있다.
DDL 생성 기능
• 제약조건 추가
ex. 회원 이름은 필수, 10자 초과X -> @Column(nullable = false, length = 10)
• 유니크 제약조건 추가
ex. @Table(uniqueConstraints = {@UniqueConstraint( name = "NAME_AGE_UNIQUE",
columnNames = {"NAME", "AGE"} )})
*DDL 생성 기능은 DDL을 자동 생성할 때만 사용되고 JPA의 실행 로직에는 영향을 주지 않는다. 따라서 스키마 자동 생성 기능을 사용하지 않고 직접 DDL을 만든다면 사용할 이유가 없다. 이 기능을 사용하면 애플리케이션 개발자가 엔티티만 보고도 손쉽게 다양한 제약조건을 파악할 수 있는 장점이 있다.
필드와 컬럼 매핑
@Column: 컬럼 매핑

유니크 제약조건은 컬럼에 직접 부여하기 보다 @Table을 통해서 많이 사용한다.
columnDefinition은 특정 DB에 종속적인(방언) 옵션에 사용한다.
@Enumerated: enum 타입 매핑
속성(value)
• EnumType.ORDINAL: enum 순서를 데이터베이스에 저장
• EnumType.STRING: enum 이름을 데이터베이스에 저장
(기본값: EnumType.ORDINAL / 권장: EnumType.STRING)
@Temporal: 날짜 타입 매핑
Date, Calendar 타입에 사용
*참고: LocalDate, LocalDateTime을 사용할 때는 생략 가능(최신 하이버네이트 지원)
속성(value)
• TemporalType.DATE: 날짜, 데이터베이스 date 타입과 매핑 (예: 2013–10–11)
• TemporalType.TIME: 시간, 데이터베이스 time 타입과 매핑 (예: 11:11:11)
• TemporalType.TIMESTAMP: 날짜와 시간, 데이터베이스 timestamp 타입과 매핑(예: 2013–10–11 11:11:11)
@Lob: BLOB, CLOB 매핑 (비구조화 대형 객체)
• 매핑하는 필드 타입이 문자면 CLOB 매핑, 나머지(이진)는 BLOB 매핑
• 속성 없이 자동으로 타입을 지정해준다.
• CLOB: String, char[], java.sql.CLOB
• BLOB: byte[], java.sql.BLOB
@Transient: 특정 필드를 컬럼에 매핑하지 않음(매핑 무시)
데이터베이스와 무관. 메모리에서만 사용
기본 키 맵핑
@Id @GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Id: 기본키 지정
• Id 값 직접 할당 시 @Id만 사용
@GeneratedValue: 기본키 값 자동 생성
• strategy
1. IDENTITY
데이터베이스에 위임, MYSQL. 영속성 컨텍스트에 의해 관리되려면 반드시 id 값이 있어야 한다. 그러나 트랜잭션 커밋 시점에 INSERT SQL 실행 한 이후에야 ID 값을 알 수 있기 때문에, IDENTITY 전략은 em.persist() 시점에 즉시 쿼리를 실행 하고 DB에서 식별자를 조회한다. 즉, persist 시점에 Id 필드 값이 채워진다.
2. SEQUENCE
유일한 값을 순서대로 생성하는 데이터베이스 시퀀스 오브젝트 사용, ORACLE. @SequenceGenerator가 필요하며 테이블(엔티티)마다 시퀀스 오브젝트를 다르게 생성하여 매핑할 수 있다. em.persist() 시점에 시퀀스 오브젝트에 다음 시퀀스를 요청하여 id 필드를 채운다. INSERT SQL은 트랜잭션 커밋 시점에 호출된다. 즉, 네트워크를 2번 탐.
@Entity
@SequenceGenerator(
name = “MEMBER_SEQ_GENERATOR",
sequenceName = “MEMBER_SEQ", //매핑할 데이터베이스 시퀀스 이름
initialValue = 1, allocationSize = 1)
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE,
generator = "MEMBER_SEQ_GENERATOR")
private Long id;
...
3. TABLE
데이터베이스 시퀀스를 흉내내는 키 생성용 테이블 사용, 모든 DB에서 사용. @TableGenerator 필요
@Entity
@TableGenerator(
name = "MEMBER_SEQ_GENERATOR",
table = "MY_SEQUENCES",
pkColumnValue = “MEMBER_SEQ", allocationSize = 1)
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.TABLE,
generator = "MEMBER_SEQ_GENERATOR")
private Long id;
...
을 실행하면 DB 내에 키 생성용 테이블로 지정한 MY_SEQUENCES 라는 이름의 테이블이 생성된다.
sequence_name(pk) = 시퀀스 컬럼명, next_val = 시퀀스 값
create table MY_SEQUENCES (
sequence_name varchar(255) not null,
next_val bigint,
primary key ( sequence_name )
)
4. AUTO
데이터베이스 방언에 따라 IDENTITY, SEQUENCE, TABLE 중 자동 지정, 기본값
***SEQUENCE, TABLE의 성능 최적화***
allocationSize 속성(기본값:50)을 사용할 수 있다. 동시성 문제 없이 한 번 시퀀스 오브젝트를 호출할 때 allocationSize 만큼의 시퀀스를 받아와서 메모리 상에서 사용한다.
권장하는 식별자 전략
• 기본 키 제약 조건: null 아님, 유일, 변하면 안된다.
• 미래까지 이 조건을 만족하는 자연키는 찾기 어렵다. 대리키(대체키)를 사용하자.
• 예를 들어 주민등록번호도 기본 키로 적절하기 않다.
• 권장: Long형 + 대체키 + 키 생성전략 사용
*대체키: 테이블에서 입력 데이터의 어떤 열(자연키)이 아닌 시스템쪽에 독립적으로 할당된 키
<Database Language>
- DDL(Data Definition Language)
테이블과 같은 데이터 구조를 정의하는데 사용되는 명령어. CREATE, ALTER, DROP, RENAME, TRUNCATE
- DML(Data Manipulation Language)
데이터베이스에 들어 있는 데이터에 대해 조회, 검색, 변형을 위한 명령어. SELECT, INSERT, UPDATE, DELETE
- DCL(Data Control Language)
데이터베이스에 접근하고 객체들을 사용하도록 권한을 주고 회수하는 명령어. GRANT, REVOKE
- TCL(Transaction Control Language)
DML에 의해 조작된 결과를 작업단위(트랜잭션) 별로 제어하는 명령어. COMMIT, ROLLBACK, SAVEPOINT
'Advance I > Springboot & JPA' 카테고리의 다른 글
| 22.06.02 (0) | 2022.06.02 |
|---|---|
| 22.06.01 (0) | 2022.06.02 |
| 22.05.29 (0) | 2022.05.29 |
| 22.05.28 (0) | 2022.05.28 |
| 22.05.26 :: 자바 ORM 표준 JPA 프로그래밍 - 기본편 (0) | 2022.05.28 |