엔티티 매핑(entity mapping)은 자바 클래스와 필드를 테이블과 컬럼에 대응시키는 JPA(Jakarta Persistence)의 기본 설정이다. 애너테이션은 jakarta.persistence 패키지에 있다. 테이블 사이의 외래키를 참조로 옮기는 일은 JPA 연관관계 매핑에서 다룬다.
@Entity
@Table(name = "contact_msg")
public class Contact {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "mobile_num", nullable = false, length = 20)
private String mobileNum;
@Enumerated(EnumType.STRING) // 'OPEN', 'CLOSED' 같은 이름으로 저장
private Status status;
@Transient // 컬럼과 연결하지 않음
private String confirmEmail;
protected Contact() {} // JPA가 쓰는 인자 없는 생성자
}클래스와 테이블
@Entity: 이 클래스가 엔티티라는 표시다. 명세는 public 또는 protected인 인자 없는 생성자를 요구하고, 클래스와 영속 필드가final이면 안 된다고 정한다. Hibernate는 이보다 느슨하지만,final이면 지연 로딩용 프록시를 만들 수 없다@Table: 테이블 이름·스키마를 따로 정할 때 붙인다. 없으면 엔티티 이름을 테이블 이름으로 쓴다@Column: 컬럼 이름과nullable·length·unique·insertable·updatable같은 속성을 정한다. 붙이지 않은 필드도 영속 필드가 되고, 컬럼 이름은 필드 이름에서 정해진다@Transient: 저장하지 않을 필드에 붙인다. 비밀번호 확인 입력처럼 화면에서만 쓰는 값이 예다
기본키 생성 전략
@Id로 기본키 필드를 정하고, 값을 자동으로 만들려면 @GeneratedValue(strategy = ...)를 붙인다.
| 전략 | 동작 |
|---|---|
IDENTITY | DB의 identity(자동 증가) 컬럼. INSERT를 해야 id를 알 수 있다 |
SEQUENCE | DB 시퀀스에서 값을 받는다. 이름을 안 주면 Hibernate는 테이블명_seq를 쓴다 |
TABLE | 키 값을 보관하는 별도 테이블(Hibernate 기본 이름 hibernate_sequences)을 쓴다 |
AUTO | 기본값. 구현체가 고른다. Hibernate는 숫자 타입이면 시퀀스, DB가 시퀀스를 지원하지 않으면 테이블 방식을 쓴다 |
IDENTITY는 행을 실제로 넣어야 id가 정해지므로, Hibernate가 그 엔티티의 INSERT를 JDBC 배치로 묶지 못한다. 새 행을 한꺼번에 많이 넣는 엔티티라면 SEQUENCE를 검토한다.
enum은 STRING으로
@Enumerated를 붙이지 않거나 타입을 지정하지 않으면 EnumType.ORDINAL로 저장된다(변환기나 @EnumeratedValue가 없을 때). ORDINAL은 enum 선언 안에서의 위치(0부터)를 정수로 넣는다. 그래서 상수 사이에 새 값을 끼우거나 순서를 바꾸면 이미 저장된 숫자가 다른 상수를 가리키게 된다. EnumType.STRING은 상수 이름을 저장하므로 순서 변경에 안전하고, DB를 직접 볼 때도 읽기 쉽다. 대신 상수 이름을 바꾸면 기존 데이터를 같이 고쳐야 한다.
JdbcTemplate에서 옮길 때 바뀌는 점
- DAO와 RowMapper가 하던 "행 → 객체" 변환을 엔티티 매핑이 맡고, DAO는 리포지터리 인터페이스로 바뀐다(JDBC와 JdbcTemplate)
- 필드
mobileNum이 컬럼mobile_num에 붙는 것은 JPA 규칙이 아니라 스프링 부트의 기본 설정 덕분이다. 부트는 물리 이름 전략으로CamelCaseToUnderscoresNamingStrategy를 써서 카멜 표기를 밑줄로 바꾸고 소문자로 만든다. Hibernate 기본 규칙은 컬럼 이름을 필드 이름과 같게 둔다 - 부트는
@SpringBootApplication이 정하는 자동 구성 패키지(auto-configuration package)에서 엔티티와 리포지터리를 찾는다.@EntityScan과@EnableJpaRepositories는 엔티티·리포지터리가 그 밖에 있을 때만 붙인다 - 생성·수정 시각 같은 공통 컬럼은
@MappedSuperclass로 모으고 자동 기록은 JPA Auditing을 쓴다 - 엔티티는 영속성 컨텍스트가 관리하므로, 바뀐 필드는 UPDATE를 직접 쓰지 않아도 커밋 때 반영된다(더티 체킹)
엔티티에 Lombok @Data를 쓰지 않는 이유는 Lombok과 JPA 연관관계 매핑을 본다.
명세: Jakarta Persistence 3.2 §2.1 The Entity Class
출처: Hibernate ORM User Guide: POJO Models · Generated identifier values · Using IDENTITY columns · @Enumerated · Jakarta Persistence API: Enumerated · Transient · Java SE: Enum.ordinal() · Naming strategies · Spring Boot 문서: Configure Hibernate Naming Strategy · Entity Classes · Spring Data JPA Repositories · Auto-configuration Packages