Question
- 데이터베이스 스키마 자동 생성 기능은 어떻게 활용하는 것이 좋은가?
- @Entity 어노테이션에 대해 설명하시오
- @Temporal이 의미하는 것은 무엇이며 이 어노테이션이 없어도 되게 하는 자바 클래스는?
- @Enumerated는 어떤 타입으로 쓰는게 좋은가?
- @Transient는 무엇을 의미하는가?
- @GeneratedValue Identity에 대해 설명하시오
- @GeneratedValue Sequence에 대해 설명하시오
- 식별자는 어떻게 정의하는게 좋은가?
데이터베이스 스키마 자동 생성 기능
- 애플리케이션 실행 시점에 DDL 자동 실행
- 테이블 중심 -> 객체 중심 가능
- 방언을 통해 데이터베이스에 맞는 적절한 DDL 생성
- 이 기능은 운영서버에는 위험해 사용하지 않고 테스트용 또는 로컬 환경에서 사용
- hibernate.hbm2ddl.auto=create 이런식으로 정의해서 사용
- create: 기존 테이블 삭제 후 다시 생성
- create-drop: create와 같으나 종료 시점에 테이블 드랍
- update: 변경분만 반영(운영 DB에는 사용하면 안됨)
- validate: 엔티티와 테이블이 정상 매핑되었는지만 확인
- none: 사용하지 않음
- 개발 초기: create/update
- 테스트 서버: update/validate
- 스테이징 운영: validate/none
@Entity
- @Entity가 붙은 클래스는 JPA가 관리하게 됨
- 파라미터가 없는 public 또는 protected 생성자가 꼭 필요함
- final, enum, interface, inner 클래스 사용 불가
- 저장할 필드에 final 사용 불가
- 기본값은 클래스 이름을 그대로 사용하지만 name 속성으로 정의 가능
어노테이션 맵핑
- @Column: 컬럼 맵핑
- @Temporal: 날짜 맵핑
- TemporalType.DATE: 2013-10-11과 같은 형식
- TemporalType.TIME: 11:11:11과 같은 형식
- TemporalType.TIMESTAMP: 2013-10-11 11:11:11과 같은 형식
- LocalDate, LocalDateTime을 사용하면 생략 가능
- @Enumerated: enum 타입 맵핑
- EnumType.ORDINAL: enum 순서를 숫자로 데이터베이스에 저장(기본값)
- EnumType.STRING: enum 이름을 데이터베이스에 저장
- ORDINAL은 ENUM의 순서를 바꾸면 숫자도 바뀌어 위험하기에 STRING을 사용해야함
- @Lob: BLOB, CLOB 맵핑
- 맵핑하는 필드 타입이 문자면 CLOB 맵핑, 나머지는 BLOB 맵핑
- CLOB: String, char[], java.sql.CLOB
- BLOB: byte[], java.sql.BLOB
- @Transient: 맵핑하지 않기
@ Column
| 속성 |
설명 |
기본값 |
| name |
매핑할 테이블의 열 이름을 지정합니다. |
필드명과 동일 |
| unique |
true로 설정하면 해당 열에 유니크 제약 조건이 설정됩니다. |
false |
| nullable |
true로 설정하면 해당 열에 NULL 값을 허용합니다. |
true |
| insertable |
true로 설정하면 삽입(insert) 시 해당 열 값을 포함시킵니다. |
true |
| updatable |
true로 설정하면 갱신(update) 시 해당 열 값을 포함시킵니다. |
true |
| columnDefinition |
데이터베이스 특정 DDL을 직접 정의할 수 있습니다. |
빈 문자열 (기본 데이터베이스 DDL) |
| table |
매핑할 테이블의 이름을 명시합니다. (다른 테이블과의 중복 방지) |
기본 테이블명 |
| length |
문자열 자료형(VARCHAR)의 경우 열 길이를 지정합니다. |
255 |
| precision |
BigDecimal 자료형의 경우 열의 정밀도를 지정합니다. (숫자 전체 자리수) |
0 (해당 없음) |
| scale |
BigDecimal 자료형의 경우 소숫점 이하 자리수를 지정합니다. (정밀도와 함께 사용) |
0 (해당 없음) |
| insertable |
해당 필드를 데이터베이스 INSERT 구문에 포함시킬지 여부를 정의합니다. |
true |
| updatable |
해당 필드를 데이터베이스 UPDATE 구문에 포함시킬지 여부를 정의합니다. |
true |
기본 키 맵핑 방법
- 직접 할당: @Id만 사용
- 자동 할당: @GeneratedValue
- IDENTITY: 데이터베이스에 위임하며 주로 MYSQL에서 주로 사용
- SEQUENCE: 데이터베이스 시퀀스 오브젝트를 사용하며 Oracle, PostgreSQL에서 주로 사용
- @SequenceGenerator를 사용해야함
- TABLE: 키 생성용 테이블을 하나 만들어 DB 시퀀스를 흉내내는 전략
- @TableGenerator 필요하며 모든 DB에 적용 가능한 장점이 있으나 성능 문제로 잘 사용하지 않음
- AUTO: 방언에 따라 자동 지정, 기본값
@GeneratedValue - Identity
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
- 기본키 생성을 DB에 위임
- 주로 MySQL, PostgreSQL, SQL Server에서 사용(MySQL의 AUTO_INCREMENT)
- JPA는 주로 트랜잭션 커밋 시점에 INSERT SQL을 실행
- AUTO_INCREMENT는 DB에 INSERT SQL을 실행한 이후에 ID 값을 알 수 있음
- IDENTITY 전략은 em.persist() 시점에 즉시 INSERT SQL을 실행하고 DB에서 식별자를 조회
@GeneratedValue - Sequence
@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;
| 속성 |
설명 |
기본값 |
| name |
시퀀스 생성기를 식별하기 위한 이름을 지정합니다. |
필수값 (기본값 없음) |
| sequenceName |
데이터베이스에 있는 실제 시퀀스 이름을 지정합니다. |
기본값 없음 |
| initialValue |
시퀀스의 초기 값을 지정합니다. 첫 번째 값이 반환될 때 시작하는 값입니다. |
1 |
| allocationSize |
시퀀스가 한 번에 증가할 수 있는 값의 수를 지정합니다. 최적화에 사용됩니다. |
50 |
| schema |
시퀀스가 존재하는 스키마 이름을 지정합니다. |
기본 스키마 |
| catalog |
시퀀스가 존재하는 카탈로그 이름을 지정합니다. |
기본 카탈로그 |
- 시퀀스는 유일한 값을 순서대로 생성하는 데이터베이스 오브젝트
- 오라클, PostgreSQL, H2 등에서 사용
권장하는 식별자 전략
- 기본 키 제약 조건: Not Null, Unique, Not Change
- 미래까지 이 조건을 만족시키는 자연키는 찾기 어려워 대체키를 사용하는게 좋음
- 예를 들어, 주민등록번호도 유일하긴 하지만 나라에서 저장하지 말라고 하면 저장 못하는 등의 문제가 있음.
- 권장은 Long + 대체키 + 키 생성전략