@Data @Id 동시 사용 시 문제점

계리·2024년 8월 10일
0

상황은 이렇다.

  • 데이터베이스에 이미 데이터가 삽입되어 있는 상태
  • 이 상태에서 데이터를 삽입하려고 하는데 오류 발생
  • 오류는 Unique index or primary key violation: "PRIMARY KEY ON PUBLIC.ITEM(ID)

Item.java

package com.example.shop;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import lombok.Data;

@Entity
@Data
public class Item {
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    public Long id;
    private String title;
    private Integer price;
}

Item 클래스(엔티티)에서 @Data 어노테이션은 Lombok 라이브러리, @Id 어노테이션은 JPA 라이브러리이다

먼저 오류에 대해 확인을 해보면 기본키(id) 값이 이미 있는데 생성을 하려고 해서 기본키 위반에 해당한다고 오류가 발생했다.

그래서

Item 클래스(엔티티)에서 어노테이션 변경을 해봤다.

Item.java

package com.example.shop;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@Entity
@Getter
@Setter
@ToString
public class Item {
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    public Long id;
    private String title;
    private Integer price;
}

@Getter @Setter 어노테이션을 이용해서 데이터를 삽입했을 때는 이상 없이 됐다.

그럼 왜 @Data 어노테이션을 사용하면 Unique index or primary key violation: "PRIMARY KEY ON PUBLIC.ITEM(ID) 오류가 발생하는지 검색을 해봤는데 잘 나오지 않는 것 같아 ChatGPT에게 물어봤다.

  • @Data 어노테이션을 사용하면 자동으로 equals와 hashcode 메서드를 생성하는데 id 필드가 있어 같이 id 필드가 포함된 상태에서 hashcode가 생성된다.

  • @Id @GeneratedValue(strategy = GenerationType.IDENTITY)는 데이터베이스에서 기본키 값을 자동생성하는 어노테이션이다. 즉 JPA가 엔티티를 데이터베이스에서 저장할 기본키 값이 자동으로 생성된다.

  • 여기서 이미 1번 기본키 값이 있는 상태에서 새로운 item 객체를 생성하면 동일한 hashcode값을 가진 item객체가 생성될 수 있다.

  • 그러면 데이터베이스에서는 새로운 객체를 저장하려고 할 때 동일한 id 값을 가진 데이터로 인식되어 해당 오류가 발생하게 된다.

라는 답변이 왔다.

해당 오류에 관해 검색해보다가 어떤 블로그(참고 블로그)를 봤는데 @Data 어노테이션을 Entity에서는 사용하지 않는다고 정리해둔 글이 있는데 데이터베이스와 관련이 있기 때문에 사용을 할 경우 위험할 수 있다는 부분이 아마 이 부분이지 않을까 싶기도 한다.

좀 더 쉽게 얘기하면 @Data 어노테이션에서 데이터베이스와 같은 id값을 생성할 수도 있고 그러면 기존에 데이터베이스에 저장되어 있던 id값이 있는 상태에서 저장하려고 해서 기본키 위반에 해당하는 상황이 나올 수 있다 라고 정리가 되지 않을까 싶다.

엔티티에서 안 쓰는 것이 좋다고 하지만 어떤 해결방법이 있는지 알아보자.

일단 id값을 equals와 hashcode 계산에서 제외를 하면 된다. 그럴려면 위에서 @Data 어노테이션 대신

  • @Getter @Setter를 이용해도 되고
  • @EqualsAndHashCode(exclude = "id")를 사용해도 된다.
@Data
@EqualsAndHashCode(exclude = "id")
@Entity
public class Item {
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    private String title;
    private Integer price;
}

참고

profile
gyery

0개의 댓글