엔티티 매핑 소개
- 객체와 테이블 매핑 : @Entity / @Table
- 필드와 칼럼 매핑 : @Column
- 기본 키 매핑 : @Id
- 연관관계 매핑 : @ManyToOne / @JoinColumn
객체와 테이블 매핑
1. @Entity
- @Entity 애노테이션이 붙은 클래스는 JPA가 관리한다.
- 엔티티라고 부른다.
- JPA를 사용해서 테이블과 매핑할 클래스에는 @Entity를 무조건 붙여야 한다.
- 주의
- 기본 생성자가 필수다.
- 파라미터가 없는 public 또는 protected 생성자가 존재해야한다.
- JPA가 객체를 동적으로 사용하거나 프록싱 기술을 쓰기 위해선 기본 생성자가 필요하기 때문이다.
- final 클래스 / enum / interface / inner 클래스에는 @Entity 애노테이션을 사용할 수 없다.
- DB에 저장할 필드값에 final 을 붙이면 안된다.
- 기본 생성자가 필수다.
🔍 주의 사항
- 기본 생성자가 무조건 정의되어 있어야 한다.
- 파라미터가 없는 public 또는 protected 생성자가 존재해야한다.
- JPA가 객체를 동적으로 사용하거나 프록싱 기술을 쓰기 위해선 기본 생성자가 필요하기 때문이다.
🔍 @Entity 속성
name 속성
- JPA에서 사용할 엔티티 이름을 지정한다.
- 기본값: 클래스 이름을 그대로 사용한다.
- 예) Member
name 속성 사용 예시
@Entity(name = "hello")
public class Member {...}
- 같은 클래스 이름이 없으면 name 속성을 쓰기 보단 가급적 기본값을 사용하는 것이 좋다.
2. @Table
- @Table 애노테이션은 엔티티와 매핑할 테이블을 지정한다.
🔍 @Table 속성
속성 | 기능 | 기본 값 |
name | 매핑할 테이블 이름 지정 | 엔티티 이름을 사용한다. |
catalog | 데이터베이스 catalog 매핑 | |
schema | 데이터베이스 schema 매핑 | |
uniqueConstraints (DDL) | DDL 생성 시에 유니크 제약 조건 생성 |
데이터베이스 스키마(schema) 자동 생성
- 데이터베이스 스키마 자동생성 기능은 객체에 정의한 정보를 바탕으로 테이블을 만들어주는 기능이다.
- JPA는 데이터베이스 스키마를 자동으로 생성하는 기능을 지원한다.
- 애플리케이션 실행 시점에 DB 테이블을 생성하는 기능이다.
- 데이터 스키마 자동 생성 기능은 운영 서버에선 절대 사용하면 안된다.
- 개발 단계 또는 로컬 PC일 때만 사용할 것을 권장한다.
- JPA는 데이터베이스 방언을 활용해서 데이터베이스에 맞는 적절한 DDL을 생성해준다.
- 이렇게 생성된 DDL은 개발 서버에서만 사용할 것. 운영서버에 사용하면 안된다.
- 생성된 DDL을 운영서버에 굳이 사용한다면 다듬고 사용할 것.
1. 데이터베이스 스키마 자동 생성 속성
🔍 hibernate.hbm2ddl.auto
옵션 | 설명 |
create | 기존 테이블을 삭제 후 다시 생성한다. (DROP + CREATE) |
create-drop | create와 같으나 종료시점에 테이블을 DROP 한다. |
update | 변경 부분만 반영한다. (절대 운영 DB에 사용하면 안된다.) 변경 부분이 필드 추가일 때만 적용된다. 필드 삭제인 경우 적용 안됨. |
validate | 엔티티와 테이블이 정상 매핑되었는지만 확인한다. |
none | 아무 기능도 사용하지 않는다. |
🔍 사용 방법
<property name="hibernate.hbm2ddl.auto" value="create" />
- persistence.xml 파일에서 추가하면 된다.
🧷 참고. 스키마 (schema)
- 스키마는 데이터베이스 구조를 의미한다.
- 정확히 말해서 개체의 특성을 나타내는 속성(Attribute)과 속성들의 집합으로 이루어진 개체(Entity), 개체 사이에 존재하는 관계(Relation)에 대한 정의와 이들이 유지해야할 제약 조건을 기술한 것이다.
🧷 참고. DDL (Data Definition Language)
- 객체의 생성, 변경, 삭제 명령어를 의미한다.
- 예를 들어 create / alter / drop / rename 등이 있다.
- shcema, domain, table, view, index를 정의, 변경 삭제할 때 사용하는 언어다.
- 한마디로 데이터베이스의 스키마(테이블 명, 열 이름 등)를 만들어주는 SQL문 집합이다.
2. 스키마 사용시 주의사항
- 운영 서버에 절대 create / creat-drop / update 속성을 사용하면 안된다.
- 개발 초기 단계 (나 홀로 개발)인 경우에는 create 또는 update 속성 정도는 사용해도 된다.
- 테스트 서버 단계 (여러 개발자와 협업)에서는 update 또는 validate 속성 정도는 사용해도 된다.
- 스테이징과 운영 서버에는 validate 또는 none 속성 정도만 사용할 것.
- 사실 모든 서버에 none 속성이 제일 좋다. 그냥 이 기능을 안쓰는 것을 권장한다.
- 스키마를 사용하는 것 보다 본인이 직접 스크립트를 작성해서 적용하는 것이 좋다.
3. DDL 생성 기능
- 제약 조건 추가 : ex) 회원 이름은 필수, 10자 초과 X
- @Column(nullable = false, length = 10)
- 유니크 제약 조건 추가
- @Table(uniqueConstraints = {@UniqueConstraint( name = "NAME_AGE_UNIQUE", columnNames = {"NAME", "AGE"} )})
- DDL 생성 기능은 DDL을 자동 생성할 때만 사용되고 JPA의 실행 로직에는 영향을 주지 않는다.
필드와 컬럼 매핑
package hellojpa;
import javax.persistence.*;
import java.util.Date;
@Entity
public class Member {
public Member() {
}
@Id
private Long id;
@Column(name = "name")
private String username;
private Integer age;
@Enumerated(EnumType.STRING)
private RoleType roleType;
@Temporal(TemporalType.TIMESTAMP)
private Date createdDate;
@Temporal(TemporalType.TIMESTAMP)
private Date lastModifiedDate;
@Lob
private String description;
@Transient
private String temp;
}
- 위 코드에서 RoleType 타입은 개발자가 직접 만든 Enum 클래스 타입이다.
1. 매핑 어노테이션 종류
어노테이션 | 설명 |
@Column | 컬럼(속성) 매핑 |
@Temporal | 날짜 타입 매핑 |
@Enumerated | enum 타입 매핑 |
@Lob | BLOB / CLOB 매핑 |
@Transient | 특정 필드를 컬럼에매핑하지 않는다. (매핑 무시) |
2. @Column
- 컬럼을 매핑할 때 사용한다.
속성 | 설명 | 기본 값 |
name | - 필드와 매핑할 테이블의 컬럼 이름 | 객체의 필드 이름 |
insertable updatable |
- 등록 가능 여부 - 변경 가능 여부 |
TRUE |
nullable (DDL) | - null 값의 허용 여부를 설정한다. - false로 설정하면 DDL 생성 시에 not null 제약 조건이 붙는다. - 자주 쓰인다. |
|
unique (DDL) | - @Table의 uniqueConstraints와 같지만 한 컬럼에 간단히 유니크 제약 조건을 걸 때 사용한다. - 자주 안쓰인다. → 제약 조건의 이름이 너무 난수값이라 알아보기 힘들기 때문 - @Table(uniqueConstraint())에 사용하는 것을 권장한다. |
|
columnDefinition (DDL) | - 데이터베이스 칼럼 정보를 직접 줄 수 있다. - ex) varchar(100) defualt 'EMPTY' |
필드 자바 타입과 방언 정보를 사용 |
length (DDL) | - 문자 길이 제약 조건. - String 타입에만 사용한다. |
255 |
percision scale (DDL) |
- BigDecimal 타입에 사용한다. (BigInteger타입도 사용 가능) - percision은 소수점을 포함한 전체 자릿수다. - scale은 소수의 자릿수다. - 참고로 double, float 타입에는 적용되지 않는다. - 아주 큰 숫자나 정밀한 소수를 다룰 때 사용한다. |
percision = 19 scale = 2 |
3. @Enumerated
- 자바 enum 타입을 매핑할 때 사용한다.
속성 | 설명 | 기본 값 |
value | EnumType.ORDINAL : enum 순서를 데이터베이스에 저장 EnumType.STRING : enum 이름을 데이터베이스에 저장 |
EnumType.ORDINAL |
- 무조건 EnumType.STRING 으로 사용할 것.
- enum 타입이 추가 / 변경 / 삭제가 되어 순서가 달라질 경우 사이트 이펙트가 생긴다.
4. @Temporal
- 날짜 타입(java.util.Date, java.util.Calendar)을 매핑할 때 사용한다.
- 지금은 잘 안쓰인다.
- 왜냐하면 LocalDate(년월), LocalDateTime(년월일)을 사용할 때는 생략이 가능하다. (최신 하이버네이트에서 지원한다.)
속성 | 설명 | 기본 값 |
value | - TemporalType.DATE : 날짜, 데이터베이스 date 타입과 매핑 (예 : 2012-10-11) - TemporalType.TIME : 시간, 데이터베이스 time 타입과 매핑 (예 : 10:06::22) - TemporalType.TIMESTAMP : 날짜와 시간, 데이터베이스 timestamp 타입과 매핑 (예 : 2013-10-11 11:05:35) |
5. @Lob
- 데이터베이스 BLOB / CLOB 타입과 매핑한다.
- @Lob 어노테이션에는 지정할 수 있는 속성이 없다.
- 매핑하는 필드 타입이 문자(String / char[])면 CLOB으로 매핑된다.
- 나머지는 BLOB으로 매핑된다.
6. @Transient
- 필드 매핑을 하고 싶지 않을 때 사용한다.
- 데이터베이스에 저장과 조회를 하지 않는다.
- 주로 메모리상에만 임시로 어떤 값을 보관하고 싶을 때 사용한다.
기본 키 매핑
1. 기본 키 매핑 어노테이션
- @Id
- @GeneratedValue
@Id @GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
2. 기본 키 매핑 방법
- 직접 할당 : @Id 애노테이션만 사용
- 자동 생성 : @Id 애노테이션 + @GeneratedValue 애노테이션 둘 다 사용
🔍 PK 값 직접 할당
- @Id 애노테이션만 사용한다.
@Id
privat Long id;
🔍 PK 값 자동 생성
- @Id 애노테이션, @GeneratedValue 애노테이션 같이 사용한다.
@Id @GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
- @GeneratedValue 애노테이션을 사용할 때 strategy 속성 값을 지정할 수 있다.
- IDENTITY
- SEQUENCE
- TABLE
- AUTO
✔ IDENTITY
- PK 값 생성을 데이터베이스에 위임한다.
- 주로 MySQL / PostgreSQL / SQL Server / DB2 / MariaDB 에서 사용한다.
- JPA는 보통 트랜잭션 커밋 시점에서 INSERT SQL 구문을 DB에 전달한다.
- 하지만 AUTO_INCREMENT는 DB에 INSERT SQL을 실행 한 후에 PK 값을 알 수 있다.
- 그렇기에 IDENTITY 속성값은 사용할 경우 em.persist() 가 호출될 때 바로 INSERT 쿼리가 DB에 전달된다.
- 쓰기 지연 기능을 사용할 수 없다.
- 애초에 쓰기 지연 기능이 성능을 획기적으로 좋게 하지 않기에 IDENTITY를 사용해도 성능 이슈가 없다.
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
✔ SEQUENCE
- 데이터베이스의 시퀀스 오브젝트(Sequence Object)를 사용하여 데이터베이스가 자동으로 pk 값을 생성해준다.
- 데이터베이스 시퀀스는 유일한 값을 순서대로 생성하는 특별한 데이터베이스 오브젝트다.
- @SequenceGenerator 애노테이션이 필요하다.
- 테이블마다 시퀀스 오브젝트를 따로 관리하고 싶으면 @SequenceGenerator에 sequenceNmae 속성을 추가한다.
- 주로 ORACLE / PostgreSQL / DB2 / H2 데이터베이스에서 사용한다.
- SEQUENCE 전략은 pk값을 설정하지 않고 generator에 매핑된 Sequence 전략에서 pk값을 얻는다.
- 해당 Sequence Object는 DB가 관리하기 때문에 DB에서 id값을 가져와야 한다.
- em.persist()를 호출하기 전에 DB의 Sequence에서 pk값을 가져온다.
- DB에서 계속 pk 값을 얻으려고 접근을 시도하면 성능 하락이 있을 수 있다.
- 따라서 initialValue 속성 값을 1로 맞추고, allocationSize를 속성을 사용하여 DB를 접근할 때 한꺼번에 많은 pk 값들을 가져와서 메모리에 저장한다.
- em,persist()가 호출될 때 영속성 컨텍스트에 엔티티가 저장될 때 마다 메모리에서 가져온 pk 값을 조회하여 순차적으로 반환 받는다.
- 만약에 메모리에서 pk 값을 다 사용했으면 또 다시 DB에 접근하여 또 한꺼번에 많은 pk값들을 가져와서 메모리에 저장한다.
- 그렇게 하여 성능 이슈를 해결했다. 동시성 문제도 없다.
@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;
@SequenceGenerator 애노테이션 속성
속성 | 설명 | 기본 값 |
name | - 식별자 생성기 이름 | 필수 |
sequenceName | - 데이터베이스에 등록되어 있는 시퀀스 이름 | hiberante_sequence |
initialValue | - DDL 생성 시에만 사용된다. - 시퀀스 DDL을 생성할 때 처음 시작하는 수를 지정한다. |
1 |
allocationSize | - 시퀀스 한 번 호출에 증가하는 수를 의미한다. (성능 최적화에 사용된다.) - 데이터 베이스 시퀀스 값이 하나씩 증가하도록 설정되어 있으면 이 값을 반드시 1로 설정해야 한다. |
50 |
catalog schema |
- 데이터 베이스 catalog 이름 - 데이터 베이스 schema 이름 |
✔ TABLE
- 키 생성 전용 테이블을 하나 만들어서 데이터베이스 시퀀스를 흉내내는 전략이다.
- @TableGenerator 애노테이션이 필요하다.
- 장점 : 모든 데이터베이스에 적용 가능
- 단점 : 성능 이슈
- 시퀀스 오브젝트는 숫자 뽑는데 최적화가 되어있지만 테이블은 최적화가 안되어 있다.
- 별도의 테이블을 생성했을 지라도 락이 걸릴 수 있어 성능의 이슈가 있다.
- 운영 서버에 TABLE 전략을 쓰면 안된다.
- 자주 안쓰인다.
@TableGenerator 속성
속성 | 설명 | 기본 값 |
name | 식별자 생성기 이름 | 필수 |
table | 키생성 테이블명 | hibernate_sequences |
pkColumnName | 시퀀스 컬럼명 | sequence_name |
valueColumnNa | 시퀀스 값 컬렴명 | next_val |
pkColumnValue | 키로 사용할 값 이름 | 엔티티 이름 |
initalValue | 초기 값. 마지막 으로 생성된 값이 기준이다. | 0 |
allocationSize | 시퀀스 한 번 호출에 증가하는 수 성능 최적화에 사용된다. |
50 |
catalog schema |
데이터 베이스 catalog 이름 데이터베이스 schema 이름 |
|
uniqueConstraint (DDL) | 유니크 제약 조건을 지정할 수 있다. |
✔ AUTO
- 데이터베이스 방언에 따라 자동 지정한다.
- 기본값이다.
3. 권장하는 식별자 전략
- 기본 키(pk)의 제약 조건
- pk 값이 null 값이면 안된다. : not null
- pk 값이 유일한 값을 가져야 한다. : unique
- pk 값이 변하면 안된다. : not update
- 비즈니스적으로 의미있는 키를 pk로 하지 않는 것이 좋다. 의미 없는 값을 pk값으로 하는 것이 좋다.
- 기본 키의 제약조건 다 만족하는 기본 키값을 찾기 힘들기 때문에 대리키(대체키)를 사용하도록 한다.
- PK 값 권장 방법
- Long 타입 형 + 대체키 + 키 생성 전략 사용
- 대체키를 uuid로 해도 된다.
- Long 타입 형 + 대체키 + 키 생성 전략 사용
👀 참고자료
https://www.inflearn.com/course/ORM-JPA-Basic/dashboard
자바 ORM 표준 JPA 프로그래밍 - 기본편 - 인프런 | 강의
JPA를 처음 접하거나, 실무에서 JPA를 사용하지만 기본 이론이 부족하신 분들이 JPA의 기본 이론을 탄탄하게 학습해서 초보자도 실무에서 자신있게 JPA를 사용할 수 있습니다., - 강의 소개 | 인프런
www.inflearn.com
https://iingang.github.io/posts/DB-schema/
[DB 데이터베이스] 스키마(Schema)의 개념 및 특징
Contents
iingang.github.io
https://jjeongil.tistory.com/1230?category=688419
SW 면접 : 데이터 베이스 : DDL, DML, DCL 개념과 차이점
DDL (Data Definition Language) 객체의 생성, 변경, 삭제 명령어를 뜻합니다. 예를 들어, create, alter, drop, rename 등이 있습니다. schema, domain, table, view, index를 정의, 변경, 삭제할 때 사용하는..
jjeongil.tistory.com
https://catsbi.oopy.io/f03397e5-a900-4f1c-956f-fc660a1ac3c5
엔티티 매핑
객체와 테이블 매핑
catsbi.oopy.io
'[JPA] > JPA 프로그래밍 - 기본편' 카테고리의 다른 글
[JPA] 다양한 연관관계 매핑 (0) | 2022.03.29 |
---|---|
[JPA] 연관관계 매핑 기초 (0) | 2022.03.28 |
[JPA] 영속성 관리 - 내부 동작 방식 (0) | 2022.03.26 |
[JPA] JPA 시작하기 (0) | 2022.03.26 |
[JPA] SQL 중심적인 개발의 문제점과 JPA 소개 (0) | 2022.03.26 |