Spring/Issue

JPA Persistable 로 엔티티 구별하기

블로그 주인장 2024. 1. 8.

토이프로젝트 진행 중 OpenAPI의 값을 데이터베이스에 저장하고

특정 주기에 기존 값과 다른 경우 update를 하는 로직을 구현하려고 했습니다.

 

많은 데이터를 특정 주기(Scheduler)에 맞게 하나의 로직에서 DB 저장과 업데이트를 동시에 해야했다.

이를 바탕으로 자료를 찾아보던 와중에 Spring Data JPA 에서 지원하는 Persistable 을 알게 되었고 해당 구현체를 사용하는 방법에 대해 알아보겠습니다.

 

Spring Data JPA save() 로직

Spring Data JPA가 제공하는 공통 인터페이스의

구현체인 SimpleJpaRepository 클래스에 있는 save() 메소드는 다음과 같다.

 

entityInformation.isNew(entity) 를 통해 

 

TRUE = persist() 호출, 

persist() 는 해당 객체를 영속성으로 만들어준다는 의미이다.

 

FALSE = merge() 호출을 한다.

merge() 는 해당 객체를 조회한 후 있다면 update, 없다면 insert를 통해 새로운 영속성 객체를 반환해준다.

 

isNew()

 

getId()의 경우에는 객체의 ID 값을 받아오는 것으로 보인다.

 

여기서 확인해볼 isNew()의 경우 객체를 받아서 신규 값의 여부를 boolean 체크를 하는 것으로 보인다.

 

 

isNew() 오버라이딩

Persistable 인터페이스를 구현해서 isNew() 메소드를 재정의해서 사용해보겠습니다.

 

 

해당 Persistable 인터페이스를 implements 해보겠습니다.

@Entity
@Getter
@Builder
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor(access = AccessLevel.PROTECTED)
public class Player implements Persistable<String> {

  //... 중략
  
  @Id
  private String id;
  
  @Transient
  protected boolean isNew = true;

  @Override
  public String getId() {
    return id;
  }

  @Override
  public boolean isNew() {
    return isNew;
  }

  public void setIsNewStatus(boolean isNew) {
    this.isNew = isNew;
  }
}

 

위의 코드는 현재 토이프로젝트에서 사용하고 있는 선수 엔티티입니다.

 

Persistable 을 이용해서 id를 현재 엔티티의 id에 넣어줍니다.

 

@Transient 어노테이션을 이용해서 isNew = true로 초기화 시켜줍니다.

 

@Transient 어노테이션은 JPA에서 엔티티의 필드값들을 영속성 객체로 관리하는데,

관리 대상에서 해당 필드나 메서드를 제외하기 위해서 사용되는 것입니다.

즉, @Transient가 적용된 필드는 변경 사항을 감지하거나 데이터베이스와 매핑하여 동기화 하지 않는다는 것입니다.

 

이로인해 데이터베이스 컬럼으로 관리될 필요가 없고, 메모리 상에 저장되어 있는 플래그 값을 통해 변경 여부를 저장해두기 위한 용도로 사용합니다.

 

 

해당 서비스 로직에서 구현한 내용을 발췌한 코드이다.

 

여기서 보면 Team 이라는 엔티티를 Dto에서 주입받는다.

 

그 후에 allTeam().contains() 함수를 활용하여 레포지토리에 있는 값과 현재 Team의 ID를 비교한다.

 

그 후에 엔티티에 변경된 isNew를 적용시켜준다.

isNew가 FALSE로 변한다면 기존 값을 사용한다는 것으로 판단하고

isNew가 TRUE로 변한다면 새로운 값이라는 것을 판단하면 된다.

 

마치며

현재, ID의 경우 OpenAPI를 통해 얻은 ID값을 Entity의 ID로 구성했다. 상황에 따라서 자동생성이 되어있는 경우라면 isNew 오버라이딩을 할 필요가 없겠지만, 만약 위처럼 만들어서 하는 경우에는 오버라이딩하여 진행하면 좋을 거 같다.

 

 

본 포스트는 작성자가 공부한 내용을 바탕으로 작성한 글입니다.
잘못된 내용이 있을 시 언제든 댓글로 피드백 부탁드리겠습니다.
항상 정확한 내용을 포스팅하도록 노력하겠습니다.

반응형

'Spring > Issue' 카테고리의 다른 글

SMTP 비동기로 보내기(@Async)  (2) 2024.01.09
Scheduler Thread Pool 사용하기  (1) 2024.01.08
@RequestParam을 Enum 타입으로 받기  (0) 2024.01.07

댓글