Spring Data JPA - 새로운 엔티티를 구별하는 방법

2022. 8. 1. 23:06·공부/JPA
반응형

출처 : 인프런 실전! 스프링 데이터 JPA

Spring Data JPA 게시글은 대부분 인프런의 김영한님의 강의인 '실전! 스프링 데이터 JPA' 기반으로 내용을 정리했습니다.

 

새로운 엔티티를 구별하는 방법

  • 새로운 엔티티를 판단하는 기본 전략
    • 식별자가 객체일 때 null로 판단
    • 식별자가 자바 기본 타입일 때 0으로 판단
      • private long id; 일 때 long에는 null이 들어갈 수 없으니 0이 들어간다.
    • Persistable 인터페이스를 구현해서 판단 로직 변경이 가능하다.

 

  • Item.class
@Entity
@Getter
public class Item {

    @Id @GeneratedValue
    private Long id;
}
  • ItemRepository.interface
public interface ItemRepository extends JpaRepository<Item, Long> {


}
  • ItemRepositoryTest.class
@Autowired ItemRepository itemRepository;

@Test
public void save() {
    
    Item item = new Item();
    itemRepository.save(item);
}

지금 코드 상황에서는 itemRepository.save()의 매개변수인 item에는 id 값이 null이다. @GeneratedValue를 하면 엔티티가 생성되는 시점이 아닌 JPA의 persist() 안에서 id 값이 부여된다. 그래서 구현체에 존재하는 save() 로직을 탈 때 새로운 객체로 판단되어 persist()가 발생한다.

여기서 문제가 발생할 수 있는데 예제 코드를 잠깐 변경해보자.

  • Item.class
@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Item {

    @Id // @GeneratedValue
    private String id;

    public Item(String id) {
        this.id = id;
    }
}
  • ItemRepositoryTest.class
@Test
public void save() {

    Item item = new Item("A");
    itemRepository.save(item);
}

위 예제 코드의 경우 구현체의 save()는 어떤 동작을 할까? 값이 있고, null과 0이 아니기때문에 이미 있는 엔티티로 인식하고 merget를 때려버린다.

이런 황당한 경우를 해결할 수 있는 방법은 Persistable이다.

 

Persistable

  • Item.class
@Entity
@EntityListeners(AuditingEntityListener.class)
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Item implements Persistable<String> {

    @Id // @GeneratedValue
    private String id;
    
    @CreatedDate
    private LocalDateTime createdDate;

    public Item(String id) {
        this.id = id;
    }
    
    @Override
    public String getId() {
        return id;
    }

    @Override
    public boolean isNew() {
        return createdDate == null;
    }
}

Persistable의 인터페이스를 가져와서 Persistable 안에 있는 isNew() 메서드를 재정의한다. isNew() 안에 개발자가 직접 새로운 객체가 맞는지, 아닌지에 대한 로직을 짜주면 된다. 위 방법은 @CreatedDate를 이용한 방법으로, @CreatedDate는 어쨌든 JPA에서 persist()가 되기 전에 호출이 되는 기능이므로 null이면 persist()가 되지 않은 객체임을 알 수 있다. 그래서 createdDate가 null이면 새로운 객체라는 로직을 추가해주면 된다.

insert 
into
    item
    (created_date, id) 
values
    (?, ?)

 

반응형
저작자표시 비영리 변경금지 (새창열림)
'공부/JPA' 카테고리의 다른 글
  • Spring Data JPA - Query By Example
  • Spring Data JPA - Specifications(명세)
  • Spring Data JPA - 스프링 데이터 JPA 구현체 분석
  • Spring Data JPA - Web 확장-페이징과 정렬
데부한
데부한
어차피 할 거면 긍정적으로 하고 싶은 개발자
    반응형
  • 데부한
    동동이개발바닥
    데부한
  • 전체
    오늘
    어제
    • 분류 전체보기 (307)
      • 방통대 컴퓨터과학과 (27)
        • 잡담 (9)
        • 3학년1학기 (17)
      • 프로젝트 및 컨퍼런스 회고 (1)
        • 프로젝트 (4)
        • 한이음 프로젝트 (0)
        • 회고 (3)
      • 공부 (165)
        • Spring (37)
        • JPA (71)
        • 인프런 워밍업 클럽_BE (10)
        • Java (6)
        • React.js (27)
        • 넥사크로 (11)
        • 기타 (3)
      • 알고리즘 (85)
        • 알고리즘 유형 (10)
        • 알고리즘 풀이 (57)
        • SQL 풀이 (18)
      • 에러 해결 (13)
      • 잡담 (7)
        • 국비교육 (2)
        • 구매후기 (5)
        • 진짜 잡담 (0)
  • 블로그 메뉴

    • Github
    • Linkedin
    • 홈
    • 방명록
    • 글쓰기
    • 관리
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    QueryDSL
    Java
    전자정부프레임워크
    인프런
    토이프로젝트
    프로그래머스
    SpringBoot를 이용한 RESTful Web Service 개발
    프론트엔드
    RESTful
    토비의스프링부트
    개발자
    자바스크립트
    SQL
    MSA
    에러해결
    방통대
    백준
    넥사크로
    oracle
    운영체제
    react
    IT
    코딩테스트
    스프링부트
    egov
    Spring
    springboot
    기출문제
    JPA
    알고리즘
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
데부한
Spring Data JPA - 새로운 엔티티를 구별하는 방법
상단으로

티스토리툴바