[TIL]엔티티 매핑과 기본키 매핑

wannabeing·2025년 4월 30일
0

SPARTA-TIL

목록 보기
15/22

✅ 엔티티 매핑

  • 객체와 테이블 매핑: @Table, @Entity
  • 필드와 컬럼 매핑: @Column
  • 연관관계 매핑: @OneToMany, @JoinColumn

@Entity

  • 기본생성자(@NoArgsConstructor)가 필수이다.
    리플렉션이라는 기술을 통해 기본생성자와 DB가 매핑하기 때문이다.
    빼먹어도 하이버네이트가 도와주지만 JPA를 사용한다면 필수로 생성하자.
    엔티티 클래스 기본생성자가 왜 필수죠?

@Temporal

@Temporal
해당 필드가 날짜(DATE), 시간(TIME),타임스탬프(TIMESTAMP) 중에
어떤 유형으로 저장되어야 하는지를 명시하기 위해 사용되는 어노테이션이다.

  • 대상: java.util.Date, java.util.Calendar
  • 용도: 날짜/시간 중 어떤 타입으로 DB에 저장할지를 명시
  • 속성:
    TemporalType.DATE: 날짜 (yyyy-MM-dd)
    TemporalType.TIME: 시간 (HH:mm:ss)
    TemporalType.TIMESTAMP: 날짜 + 시간 (yyyy-MM-dd HH:mm:ss)
    @Column(updatable = false)
    @Temporal(TemporalType.TIMESTAMP)
    private Date createdAt;
  • TIMESTAMP지원되는 미래 연도가 짧으므로
    그 이후의 날짜를 지정할 경우가 생긴다면 DATETIME으로 설정하는 것이 좋다.

💡 Java 8 이상: LocalDateTime 사용

java.time 패키지의 클래스이며, Java 8에서 도입된
날짜와 시간을 함께 표현할 수 있는 불변 객체이다.
Java 8 이상을 사용하는 경우, java.time 패키지를 사용하는 것이 권장된다.

JPA 2.2 및 Hibernate 5 이상에서는 @Temporal 어노테이션을 사용하지 않아도
MYSQL의 경우, 자동으로 TIMESTAMP or DATETIME으로 매핑된다.

@Column(updatable = false)
private LocalDateTime createdAt;

⭐️ @CreatedDate, @LastModifiedDate

JPA에서 엔티티 생성/수정 시점을 자동으로 입력해주는 어노테이션이다.

java.util.DateCalendar를 사용할 경우에는 @Temporal 어노테이션이 필수이다.

@CreatedDate
@Column(updatable = false)
private LocalDateTime createdAt;

@LastModifiedDate
private LocalDateTime updatedAt;

필요 설정

  • @EnableJpaAuditing
    JPA의 생성일/수정일 등을 자동으로 감지하도록 활성화
    위치: @SpringBootApplication이 선언된 클래스나 config 패키지
  • @EntityListeners(AuditingEntityListener.class)
    JPA 생명주기 이벤트를 감지하게 클래스 상단에 적용
  • @MappedSuperclass
    공통 필드를 가진 부모 클래스에서 자식 엔티티가 해당 필드를 상속받도록 지정.
    실제 테이블은 생성되지 않고, 상속받는 엔티티에 컬럼으로 포함됨

@Column

  • unique: 유니크 조건을 지정할 수 있다.
  • columnDefinition: 컬럼 정보를 직접 줄 수 있다.

✅ unique 속성을 지양해야하는 이유

@Entity
@Table(name = "users")
@Getter
@NoArgsConstructor
public class User {
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Long id;

	@Column(nullable = false, unique = true) // ✅ 유니크 제약
	private String email;

	@Column(nullable = false)
	private String password;

	@Column(nullable = false, unique = true)
	private String nickname; // ✅ 유니크 제약
   ....

위와 같은 User엔티티가 있다고 가정하자.

키 값이 이미지처럼 랜덤으로 설정되면 디버깅 및 예외처리에 식별하기 어려워진다.

Duplicate entry 'example@example.com' for key 'UK_8f8e4f3b8a2b3e9a'

유니크 키 제약조건 위반시 뜨는 에러 문구이다.
위와 같이 식별하기 어렵기 때문에 어떤 필드인지 파악하기 어려워진다.

따라서 @TableuniqueConstraints를 사용하는 것을 더 추천한다.


기본키 매핑 전략

보통 IDENTITY 전략을 많이 쓰게 된다.

IDENTITY

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
  • DB에 기본키 생성을 위임하는 전략이다.
  • 예시) MySQL의 AUTO_INCREMENT

SEQUENCE

  • DB의 시퀀스 객체(Sequence)를 사용해 PK를 만드는 전략이다.
  • 주로 Oracle, PostgreSQL에서 사용한다.

TABLE

  • 별도의 테이블을 만들어 기본키 값을 관리하는 전략이다.

[ ✋🏻 IDENTITY 전략의 특징 ]

JPA와 영속성 컨텍스트
JPA는 보통 객체를 영속성 컨텍스트에 등록한 후,
트랜잭션을 커밋하거나 flush()를 호출하는 시점에 INSERT 쿼리를 실행한다.

하지만 IDENTITY 전략을 사용할 경우, 예외가 발생한다.

객체를 생성할 때, Id값이 null이기 때문에
객체가 영속성 컨텍스트에 들어가기 전에, ID 값을 알아야 한다.
따라서 JPA는 IDENTITY 전략을 사용하는 엔티티를 persist()하는 즉시
DB에 INSERT 쿼리를 날려 ID 값을 받아서 1차캐시에 저장한다.

JPA 기본 동작 방식

new → persist() → 영속 상태(INSERT 미실행) → flush() or commit() → INSERT 실행

✅ IDENTITY 전략을 사용하는 JPA 동작 방식

new → persist() → INSERT 실행 (즉시 ✅) → 생성된 ID 값을 받아와 1차 캐시(영속성 컨텍스트)에 저장

출처

w3schools-java_date
unique 속성을 지양해야 하는 이유
김영한 자바 ORM 표준 JPA 프로그래밍

profile
wannabe---ing

0개의 댓글