[4] 엔티티 매핑

ttt-1-2·2026년 4월 5일

교재: 자바 ORM 표준 JPA 프로그래밍 

JPA는 다양한 어노테이션을 지원하는데 크게 4가지로 나눌 수 있다:

  • 객체와 테이블 매핑: @Entity, @Table
  • 기본 키 매핑: @Id
  • 필드와 컬럼 매핑: @Column
  • 연관관꼐 패핑: @ManyToOne, @JoinColumn

4장에서 객체와 테이블 매핑, 기본 키 매핑, 필드와 컬럼 매핑을 다룰 것이다.


1. @Entity

JPA를 사용해서 테이블과 매핑할 클래스는 @Entity 필수로 붙여야 한다.

  • 속성: name: 사용할 엔티티 이름 (기본값: 클래스 이름)
  • 주의사항:
    • 기본 생성자는 필수!
    • final 클래스, enum, interface, inner 클래스 사용할 수 없다
    • 저장할 필드에 final을 사용하면 안 된다.
public Member() {} // 직접 만든 기본 생성자

// 임의 생성자
public Member(String name) {
	this.name = name;
}

2. @Table

@Table은 엔티티와 매핑할 테이블을 지정한다.

  • 속성:
    • name: 매핑할 테이블 이름
    • catalog: catalog 기능이 있는 데이터베이스에서 catalog를 매핑한다
    • schema: schema 기능이 있는 데이터베이스에서 schema를 매핑한다
    • uniqueConstraints: DDL 생성시에 유니크 제약 조건을 만든다

3. 다양한 매핑 사용

요구사항:

  • 회원: 일반회원, 관리자로 구분한다
  • 회원 가입일 + 수정일이 있어야 한다
  • 회원 설명 필드 있어야 한다. 이 필드는 길이 제한이 없다
package jpabook.start;

import javax.persistence.*;
import java.util.Date;

@Entity
@Table(name="MEMBER")

public class Member {
	
	@Id
	@Column(name="ID")
	private String 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;
	
	//Getter, Setter
	...
}
package jpabook.start;

public enum RoleType {
	ADMIN, USER
}

4. 데이터베이스 스키마 사용

JPA는 데이터베이스 스키마를 자동으로 생성하는 기능을 지원한다. 이 기능은 persistence.xml 또는 application.yml에서 설정할 수 있다.

<property name="hibernate.hbm2ddl.auto" value="create" />
<property namee="hibernate.show_sql" value="true" />
  • [hibernate.hbm2ddl.auto] 속성:
    • create: 기존 테이블을 삭제하고 새로 생성한다
    • create-drop: 실행 시 생성하고 종료 시 삭제한다
    • update: 엔티티 변경 사항만 DB에 반영한다
    • validate: 엔티티와 DB 구조를 비교만 하고 수정하지 않는다
    • none: 아무 작업도 하지 않는다

5. DDL 생성 기능

  • 추가 제약조건이 있다: 회원 이름은 필수로 입력되어야 하고, 10자를 초과하면 안 된다.
@Column(name="NAME", nullable=false, lengeth=10) // 추가 제약조건

@Column 매핑 정보

  • nullable = false
    → DDL에서 NOT NULL 제약 조건을 설정한다.
  • length
    → DDL에서 문자 길이(컬럼 크기)를 설정한다.
  • 추가 제약조건: 유니크
@Table(name="MEMBER", uniqueConstraints = {@UniqueConstraint( //추가 //**
        name = "NAME_AGE_UNIQUE",
        columnNames = {"NAME", "AGE"} )})

엔티티의 @Column 속성들은 주로 DDL 자동 생성 시에만 사용되고 애플리케이션 실행 로직에는 영향을 주지 않는다. 하지만 엔티티만 보고도 제약조건을 쉽게 파악할 수 있어 코드 가독성과 유지보수에 도움이 된다.

6. 기본 키 매핑

JPA가 제공하는 데이터베이스 기본 키 생성 전략은 다음과 같다

  • 직접 할당: 애플리케이션에서 직접 기본 키 값을 설정한다
  • 자동 생성:
    • IDENTITY: DB의 auto increment 기능을 사용해 기본 키를 생성한다
    • SEQUENCE: DB의 시퀀스를 사용해 기본 키를 생성한다
    • TABLE: 별도의 키 생성 테이블을 사용해 기본 키를 관리한다

6.1 기본 키 직접 할당전략

기본 키를 직접 할당하려면 다음 코드와 같이 @Id 로 매핑하면 된다.

@Id
@Column(name="id")
private String id;

Board board = new Board();
board.setID("id") // 기본 키 직접할당
em.persist(board);

6.2 IDENTITY 전략

IDENTITY는 기본키 생성을 데이터베이스에 위임하는 전략이다.

IDENTITY 전략을 사용하려면 @GeneratedValue의 strategy 속성값을 GenerationType.IDENTITY로 지정하면 된다. 이전략을 사용하면 JPA는 기본 키 값을 얻어오기 위해 데이터베이스를 추가로 조회한다.

@Entity
public class Board {
	
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Long id;
	
}
private static void logic(EntityManager em) {
	Board board = new Board();
	em.persist(board);
	System.out.println("board.id = " + board.getId);
}
// 출력: board.id=1

6.3 SEQUENCE 전략

시퀀스: 유일한 값을 순서대로 생성하는 특별한 데이터베이스 오브젝트다. SEQUENCE 전략은 이 시퀀스를 사용해서 기본 키를 생성한다.

  • 시퀀스 DDL:
CREATE TABLE BOARD {
	ID INT NOT NULL PRIMARY KEY,
    DATA VARCHAR(255)
 }
 
 CREATE SEQUENCE BOARD_SEQ START WITH 1 INCREMENT BY 1;
  • 시퀀스 매핑 코드:
@Entity
@SequenceGenerator(
	name = "BOARD_SEQ_GENERATOR",
    sequenceName = "BOARD_SEQ", //매핑할 db 시퀀스 이름
    initialValue = 1, allocationSize = 1)
public class Board {
	
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE,
    					generator = "BOARD_SEQ_GENERATOR")
    private Long id;
    
    ..
}

@SequenceGenerator: 는 시퀀스 생성 방식을 정의하는 설정이고, 실제로는 @GeneratedValue에서 generator 이름을 통해 사용된다. 즉, @SequenceGenerator는 정의, @GeneratedValue는 실행 역할을 한다.

  • name: 시퀀스 생성기를 식별하기 위한 이름이다
  • sequenceName: 매핑할 데이터베이스 시퀀스 이름이다
  • initialValue: 시퀀스의 시작 값을 설정한다
  • allocationSize: 한 번에 가져올 시퀀스 값의 증가 크기를 설정하여 성능을 최적화한다
  • catalog, schema: 시퀀스가 속한 데이터베이스의 catalog와 schema를 지정한다

6.4 TABLE 전략

TABLE 전략: 키 생성 전용 테이블을 하나 만들고 여기에 이름과 값으로 사용할 컬럼을 만들어 데이터베이스 시퀀스를 흉낸다.

  • TABLE 전략 키 생성 DDL
CREATE table MY_SEQUENCES {
	sequence_name varchar(255) not null,
    next_val bigint,
    primary key (sequence_name)
 }
  • TABLE 전략 매핑 코드
@Entity
@TableGenerator(
	name = "BOARD_SEQ_GENERATOR",
    table = "MY_SEQUENCES", 
    pkColumnValue = "BOARD_SEQ", allocationSize = 1)
public class Board {
	
    @Id
    @GeneratedValue(strategy = GenerationType.TABLE,
    					generator = "BOARD_SEQ_GENERATOR")
    private Long id;
    
    ..
}

6.5 AUTO 전략

GenerationType.AUTO 는 선택한 데이터베이스 방언에 따라 IDENTITY, SEQUENCE, TABL 전략 중 하나를 자동으로 선택한다.

ex: 오라클을 선택하면 SEQUENCE, MySQL을 선택하면 IDENTITY를 사용한다.

6.6 기본 키 매핑 정리

em.persist() 를 호출한 직후에 발생하는 일을 식별자 할당 전략별로 정리하면 다음과 같다.

  • 직적 할당: persist 전에 애플리케이션에서 직접 id 값을 설정해야 한다
  • SEQUENCE: 시퀀스를 통해 id를 먼저 조회한 후 엔티티에 할당한다
  • TABLE: 키 생성 테이블에서 id를 조회하고 값을 증가시킨 후 할당한다
  • IDENTITY: 엔티티를 먼저 DB에 저장한 후 생성된 id 값을 조회한다

7. 필드와 컬럼 매핑: 레퍼런스

7.1 @Column

@Column의 속성:

  • name: 컬럼 이름을 지정한다
  • insertable: INSERT SQL에 포함할지 여부를 설정한다
  • updatable: UPDATE SQL에 포함할지 여부를 설정한다
  • table: 매핑할 테이블을 지정한다
  • nullable(DDL): NOT NULL 제약 조건을 설정한다
  • unique(DDL): UNIQUE 제약 조건을 설정한다
  • columnDefinition(DDL): 컬럼의 DDL을 직접 정의한다
  • length(DDL): 문자열 컬럼의 길이를 설정한다
  • precision, scale(DDL): 숫자의 전체 자릿수와

7.2 @Enumerated

자바의 enum 타입을 매핑할 때 사용한다

  • EnumType.ORDINAL: enum 순서를 데이터베이스에 저장
  • EnumType.STRING: enum 이름을 데이터베이스에 저장

7.3 @Temporal

날짜 타입(java.util.Date, java.util.Calendar)을 매핑할 때 사용한다.

  • value 속성:
    • TemporalType.DATE: 날짜(년,월,일)만 저장한다
    • TemporalType.TIME: 시간(시,분,초)만 저장한다
    • TemporalType.TIMESTAMP: 날짜와 시간을 모두 저장한다

7.4 @Lob

데이터베이스 BLOB, CLOB 타입과 매핑한다.

  • BLOB: byte[], java.sql.BLOB
  • CLOB: String, char[], java.sql.CLOB

7.5 @Transient

이 필드는 매핑하지 않는다. 데이터베이스에 저장하지 않고 조회하지도 않는다. 객체에 임시로 어떤 값을 보관하고 싶을 때 사용한다.

@Transient
private Integer temp;

7.6 @Access

JPA가 엔티티 데이터에 접근하는 방식을 지정한다:

  • 필드 접근: AccessType.FIELD로 지정한다. 필드에 직접 접근한다. 필드 접근 권한이 private이어도 접근할 수 있다.
  • 프로퍼티 접근: AccessType.PROPERTY로 지정한다. 접근자 getter를 사용한다.

0개의 댓글