아래의 매핑 설정을 읽어서 ddl-auto 설정 (자동 DDL 생성 옵션)을 통해 테이블의 DDL 쿼리 실행과 생성을 자동화 할 수 있다.
1. 객체와 테이블 매핑 (@Entity, @Table)
자바 클래스를 데이터베이스 테이블과 매핑할 때 사용한다. (정확히는 자바의 객체 모델과 관계형 데이터베이스의 테이블 모델을 서로 연결)
- @Entity: JPA가 관리할 테이블 대상 자체(객체)임을 선언(지정)한다.
- 기본 생성자 (파라미터가 없는 public 또는 protected 생성자)가 필수!
- final 클래스, enum, interface, inner 클래스에는 사용할 수 없다.
- DB에 저장할 필드에 final을 사용할 수 없다.
- DDL 자동 생성 시 해당 엔티티 클래스 구조를 기반으로 CREATE TABLE 엔티티명 형태의 DDL 뼈대를 만든다.
- @Table: 엔티티와 매핑할 데이터베이스 테이블명을 지정한다. (DDL 생성 시 테이블의 상세 옵션 및 이름 설정)
- 생략 시 엔티티 이름을 테이블 이름으로 기본 사용한다.
- uniqueConstraints, indexes 등의 테이블 수준 제약 조건을 설정할 수 있다
@Entity
@Table(name = "MEMBER")
public class Member {
public Member() {} // 기본 생성자 필수
}
더보기
ℹ️ @Entity 선언 시 기본 생성자 조건
기본 생성자 (public 또는 protected)가 필요한 이유
1) 리플렉션(Reflection) 및 프록시(Proxy) 객체 생성
- JPA 구현체는 데이터베이스에서 조회한 데이터를 객체로 변환할 때 자바의 리플렉션 API를 사용한다.
- 리플렉션은 클래스의 동적 객체 생성을 위해 인자(Parameter)가 없는 기본 생성자를 필요로 함.
- 만약 매개변수가 있는 생성자만 존재하면, JPA는 어떤 인자에 어떤 값을 넣어서 객체를 생성해야 할지 판단하기 힘들다.
2) private 생성자를 사용할 수 없는 이유 (protected 이상)
- JPA는 지연 로딩(Lazy Loading)을 구현하기 위해 엔티티 클래스를 상속받는 프록시(Proxy) 객체를 가상으로 만들어 사용.
- 자바에서 자식 클래스(프록시)가 부모 클래스(실제 엔티티)의 생성자를 호출하려면 생성자가 최소 protected 이상이어야 한다.
- private으로 선언하면 자식 클래스인 프록시에서 부모 생성자를 호출하지 못해 지연 로딩이나 프록시 생성이 불가능해짐.
더보기
ℹ️ 클래스 선언 시 제약 조건
1) 왜 final 클래스에 @Entity를 쓸 수 없을까?
- 지연 로딩(Lazy Loading)을 위한 프록시 생성 불가
- JPA(Hibernate)는 엔티티의 연관관계를 지연 로딩할 때, 진짜 객체 대신 실제 엔티티를 상속(Extends)받은 가짜 프록시 객체를 상속 형태로 생성한다.
- 자바에서 final 키워드가 붙은 클래스는 상속이 불가능하므로, JPA가 프록시 객체를 만들 수 없게 됨.
2) 왜 enum, interface, inner 클래스에는 지정할 수 없을까?
- enum (열거형):
- 상태 값 정의용: Enum은 고정된 상수 집합을 다루기 위해 디자인됨.
- 불변성 및 생성자 제한: Enum은 새로운 인스턴스를 동적으로 생성하거나 상태(State)를 변경할 수 있는 구조가 아님. DB의 행(Row)으로 매핑되어 상태 변화가 일어나는 데이터 구조와 맞지 않는다.
- interface (인터페이스):
- 구현체가 아님: 인터페이스는 메서드의 명세만 정의할 뿐 인스턴스(객체)를 인스턴스화할 수 없다. DB 레코드를 매핑해서 객체로 담을 실제 필드와 메모리 공간이 존재하지 않음.
- inner 클래스 (비정적 내부 클래스):
- 숨겨진 부모 참조(Outer Class Reference): 자바의 비정적(Non-static) Inner 클래스는 외부 클래스의 인스턴스 참조를 숨은 필드로 계속 가지고 있음.
- 독립성 결여: 이로 인해 독립적인 기본 생성자를 만들 수 없고, JPA가 리플렉션을 통해 객체를 생성할 때 외부 클래스의 존재 유무에 따라 생성이 차단되므로 독립적인 DB 레코드 매핑 단위로 활용할 수 없다. (단, static inner class의 경우 내부 클래스여도 외부 참조를 갖지 않아 규칙 준수 시 @Embeddable 등으로 활용이 가능.)
2. 필드와 컬럼 매핑 (@Column, @Enumerated 등)
객체의 필드를 테이블의 컬럼과 매핑할 때 사용한다.
- @Column: 컬럼 이름, 크기(length), Null 허용 여부(nullable), Unique 제약조건 등을 설정한다.
- @Enumerated: 자바의 enum 타입을 매핑할 때 사용한다.
- ⚠️ 주의: 반드시 EnumType.STRING을 사용하는 것이 권장. (EnumType.ORDINAL은 순서 숫자가 저장되어 enum이 변경될 때 데이터 혼선이 생길 수 있다.)
- @Temporal: 날짜 타입(java.util.Date, Calendar)을 매핑할 때 사용한다.
- ⚠️ 참고: Java 8 이상에서는 LocalDate, LocalDateTime을 사용할 경우 이 어노테이션을 생략해도 자동으로 매핑된다.
- @LOB: BLOB, CLOB 형태의 대용량 데이터를 매핑할 때 사용한다. (문자면 CLOB, 나머지는 BLOB)
- @Transient: DB 테이블의 컬럼과 매핑하지 않고, 메모리 내에서만 관리할 필드에 지정한다.
@Entity
public class Member {
@Column(name = "user_name", nullable = false, length = 20)
private String username;
@Enumerated(EnumType.STRING)
private RoleType roleType; // enum 매핑
private LocalDateTime createdDate; // 자동 날짜 매핑
@Transient
private int tempMemoryData; // DB 저장 제외
}
3. 기본 키(Primary Key) 매핑 (@Id, @GeneratedValue)
엔티티의 식별자(PK)를 매핑하는 전략.
- @Id: 직접 기본 키를 할당할 때 사용합니다.
- @GeneratedValue: 기본 키 생성 전략을 위임할 때 사용한다(자동 생성). 자세한 내용은 여기서.
- IDENTITY: 기본 키 생성을 데이터베이스에 위임한다. (예: MySQL의 AUTO_INCREMENT)
- SEQUENCE: 데이터베이스 시퀀스 오브젝트를 사용한다. (예: Oracle, PostgreSQL)
- TABLE: 키 생성 전용 테이블을 하나 만들어 데이터베이스 시퀀스를 시뮬레이션한다. (모든 DB에서 사용 가능하지만 성능상 불리)
- AUTO: 방언(Dialect)에 따라 위의 세 가지 전략 중 하나를 자동으로 선택한다.
@Entity
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
}
4. 연관관계 매핑 (@ManyToOne, @OneToMany 등)
객체의 참조와 테이블의 외래 키(FK)를 매핑하는 전략. 자세한 내용은 여기서.
- N : 1 (@ManyToOne): 가장 흔하게 사용되는 연관관계. (기본적인 필수 매핑 방식)
- 1 : N (@OneToMany): 1 대 N 관계를 매핑할 때 사용한다.
- 1 : 1 (@OneToOne): 1 대 1 관계를 매핑할 때 사용한다.
- N : M (@ManyToMany): N 대 N 관계는 실무에서 직접 매핑하기보다, 연결 엔티티를 만들어 1:N, N:1 관계로 풀어내는 것이 권장됩니다.
💡 Tip!
항상 외래 키(FK)가 위치한 엔티티가 연관관계의 주인(Owner)이 되도록 매핑하고, 주인이 아닌 쪽은 mappedBy 속성을 지정하는 것이 기본 원칙.
'Tech Stack > Database' 카테고리의 다른 글
| 🔌JDBC 요약 정리 (0) | 2026.07.11 |
|---|---|
| 🗃️ [JPA-03] JPA 아키텍처 구조 및 주요 API 동작 원리 (0) | 2026.07.09 |
| 🍃 JDBC, JPA 환경에 사용할 데이터베이스 설치 및 환경 설정(의존성) (0) | 2026.07.09 |
| 🗃️[JPA-02] JPA 엔티티와 영속성 컨텍스트 핵심 (+생명주기) (0) | 2026.07.09 |
| 🔌[JDBC] JDBC 개요 및 데이터베이스 연결 원리 (0) | 2026.07.09 |