Object-RDB Mapping
entity mapping
DDL(DataDefinitionLanguage)을 application 실행 시점에 자동 생성 → database schema(Tables, Field/columns, relationships ...)가 자동 생성됨
- 이때 database dialect를 사용하여 적절한 DDL생성
- 테이블 중심에서 객체 중심으로
- 개발 서버에서만 사용해야 함! (운영 서버에서는 사용 ㄴㄴ or 다듬어서 사용)
개요
| Category | Annotations |
|---|
| 객체와 테이블 매핑 | @Entity, @Table |
| 필드와 컬럼 매핑 | @Column |
| 기본 키 매핑 | @Id |
| 연관관계 매핑 | @ManyToOne, @JoinColumn |
hibernate.hbm2ddl.auto
- 운영 장비에는 절대 create, create-drop, update 사용하면 안됨
- local서버에서만 update, create사용하자
Object - table mapping
@Entity
@Entity가 붙은 클래스를 entity라 하고, JPA가 관리한다.
실제 DB 테이블과 매핑되는 핵심 클래스로, 데이터베이스의 테이블에 존재하는 컬럼들을 필드로 가지는 객체
속성 name
JPA에서 사용할 entity의 이름.
기본값 = 클래스 명
field와 Column mapping
@Column 매핑 사용
속성은 다음과 같다

enum타입의 경우 @Enumerated(EnumType.STRING)
매핑하지 않으려면 @Transient
긴 것은 @Lob이용
PrimaryKey mapping
-
기본 키 제약 조건: null 아님, 유일, 변하면 안된다.
-
but, 미래까지 이 조건을 만족하는 자연키는 찾기 어렵다. 대리키(대체키)를 사용하자.
예를 들어 주민등록번호도 기본 키로 적절하기 않다.
⟹ 권장: Long형 + 대체키 + 키 생성전략(AUTO_INCREMENT, SEQUENCE_OBJECT 사용 등)
- 직접 할당: @Id만 사용
- 자동 생성 : @GeneratedValue 사용
| Generation Strategy | Description | Database | Additional Annotation |
|---|
| IDENTITY | 데이터베이스에 위임 | MYSQL | None |
| SEQUENCE | 데이터베이스 시퀀스 오브젝트 사용 | ORACLE | @SequenceGenerator |
| TABLE | 키 생성용 테이블 사용, 모든 DB에서 사용 | All Databases | @TableGenerator |
| AUTO | 방언에 따라 자동 지정, 기본값 | Default | None |
1) IDENTITY 전략 : 기본 키 생성을 데이터베이스에 위임
- MySQL, PostgresQL,,
- JPA는 보통 트랜잭션 커밋 시점에 INSERT SQL 실행한다 그러나 AUTO_ INCREMENT는 데이터베이스에 INSERT SQL을 실행한 이후에 PK값이 나오기 때문에
- 따라서 IDENTITY 전략은 em.persist() 시점에 즉시 INSERT SQL 실행 하고 DB에서 식별자를 조회
@Entity
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
2) SEQUENCE 전략
database sequence = 유일한 값을 순서대로 생성하는 DB Object
@Entity
@SequenceGenerator(
name = "MEMBER_SEQ_GENERATOR",
sequenceName = "MEMBER_SEQ",
initialValue = 1, allocationSize = 50)
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
private Long id;

TABLE 전략
키 생성 전용 테이블을 하나 만들어서 database sequence를 흉내내는 전략
association mapping
- 객체의 reference와 table의 foreign Key를 mapping
- table은 FK로 join해서 연관 Table을 찾음
- 객체는 참조를 사용해서 연관된 객체를 찾음
1. 단방향 mapping만으로 일단 설계를 완료해야 함
테이블 설계를 같이 그리면서 객체 설계가 일어나야 함
이때 단방향으로 설계를 끝내야 함
단방향으로 이미 설계가 완료된 것
단지 역방향으로 조회하기 위해 단방향을 필요할 때만 또 추가해서 양방향을 만드는 것이다.
- JPQL에서 역방향으로 탐색해야할 일이 많음
- 어플리케이션 개발 때 추가
양방향 association
- table의 경우, FK가 다른 테이블에서 PK이므로 FK하나로 양쪽을 다 알 수 있다(양쪽으로 join가능)
- 객체의 양방향 관계는 사실상 서로 다른 2개의 단방향 관계이다.
따라서 객체의 두 관계 중 하나를 연관관계의 주인으로 지정해 이것 만이 외래키를 관리(등록, 수정)할 수 있어야 한다.
FK가 있는 쪽을 주인으로 정하자. 비즈니스적으로 중요한 쪽이 주인이 되는 것이 아니다.
- 1 : N이면 N이 주인
- 주인이 아닌쪽은 읽기만 가능
- 주인은
mappedBy속성을 사용하면 ㄴㄴ, 주인이 아닌 쪽이 mappedBy로 주인을 지정해야 함

주의점
1. 연관관계 Owner에 값을 입력해야 한다. 또한 순수한 객체 관계를 고려해 항상 양쪽에 값을 입력해야 한다.
2. 양쪽에 값을 입력할 수 있도록 association helper method를 작성하자.
3. 무한 loop
lombok에서 toString()만드는 것은 웬만하면 쓰지 마라
JSON생성 라이브러리 : controller에는 Entity를 반환하면 안된다.
3. 연관관계 mapping시 고려사항
1) 다중성 2) 단방향, 양방향 3) 연관관계의 주인
@JoinColumn(name = "매핑할 외래키 이름")
다대일 (가장 많이 쓰는.)


일대다
- 다대일의 반대
- entity가 관리하는 FK가 다른 테이블에 존재
- 연관관계 관리를 위해 추가로 UPDATE sql 실행
⟹ 다대일 양방향으로 사용하자. (객체에서 참조를 하나 더 넣는 한이 있더라도)
일대일
- DB입장에선 외래 키의 DB 유니크 제약조건이 추가된 것
- 한마디로 정리하면, 객체는 상응하는 table만 관리할 수 있다


(주 테이블에 FK가 있는 경우만 제시한 것임)
(대상 테이블에 FK가 있는 경우도 가능)
다대다 : 쓰면 안됨
- RDB는 정규화된 Table2개로 다대다 관계를 표현할 수 없음
- 연결테이블을 추가해서 일대다 + 다대일 관계로 풀어내야 함
4. 상속관계 association mapping
- RDB는 상속관계가 없음
- 조인전략을 기본으로 하되, 너무 단순하고 확장성이 없는 경우 단일테이블 전략으로 전환하자.
전략1. @Inheritance(strategy = InheritanceType.JOINED)

장점 : 1) Data가 정규화, 설계가 깔끔 2) 제약조건을 아이템에 걸어서 맞출 수 있음 3) 저장공간 효율화
단점 : 1) 조회시 join을 많이 사용, 성능 저하 2) 조회 쿼리가 복잡 3) 데이터 저장시 Insert sql 2번 호출
전략2. @Inheritance(strategy = InheritanceType.SINGLE_TABLE)

dtype을 자동으로 추가해 줌
장점 1) join이 필요가 없으므로 조회가 빠름 2) 조회 쿼리가 단순
단점 1) ((치명적)) 자식 엔티티가 매핑한 칼럼은 모두 null허용 2) 단일 테이블에 모든 것을 저장하므로 테이블이 커질 수 있어 상황에 따라 성능저하 가능
전략3. (아무도 추천하지 않는 전략) @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
@MappedSuperclass
상속관계 매핑이 전혀 아니라, 단순히 entity가 공유하는 속성을 같이 쓰고 싶을 때
주로 등록일, 수정일, 등록자, 수정자 같은 전체 엔티티에서 공통 으로 적용하는 정보를 모을 때 사용
주로 registerDate, lastModifiedDate, registorName, modifierName과 같은 전체 entity에서 공통으로 적용하는 정보를 모을 때 사용
부모 클래스를 상속 받는 자식 클래스에 매핑 정보만 제공 조회
검색 불가(em.find(BaseEntity) 불가)
직접 생성해서 사용할 일이 없으므로 추상 클래스 권장
참고로, 엔티티 객체에서 extend할 수 있는 것은 @MappedSuperclass이거나 @Entity인 엔티티만 가능하다.