[JPA] Save는 Insert인가요 update인가요?

BlackBean99·2022년 7월 9일
3

SpringBoot

목록 보기
8/20

우리가 단순히 저장을 위해 사용하던 ~~Repository.save(T Object)
이 코드는 Entity를 호출해 신규로 저장하거나 업데이트한다.
사실 이는 update, insert 두 쿼리를 구분해서 날린다는 사실 알고 있었나요?

?? 어?? 생각해본적 없는데..?

네 저도 생각해본적 없었는데..ㅎㅎ 갑자기 알게 됐슴둥..

예제를 보면서 함께 이해해봅시다.

SpringBoot Data JPA

@Test
public void SaveUpdateTest(){
	Entity en = new Entity();
    en.A = 1;
    // 첫번째 save
    entityRepository.save(en);
    Entity en2 = entityRepository.findByA(1);
    en2.A = 2;
    entityRepository.save(en2);
    
    assertThat(entityRepository.findByA(1)).isEqualTo(2);
}

위 코드를 봐보자

핵심은 Spring-Data-Jpa가 저 save() 인터페이스를 실행하게 되면 SimpleDataJpaRepository의 save를 호출한는데
이를 넘겨받은 SimpleDataJpaRepository는 EntityInformation type 필드 entityInformation을 갖고 있습니다. entityInformation에서는 Entity의 MetaData를 가지고 있어요.

내부에서 isNew에 Entity를 파라미터를 넘겨서 새롭게 생성된 Entity인지 검사합니다.

<SimpleDataJpaRepository.class>
@Transactional
@Override
publce<S extends T>S save(S entity){
	Assert.notNull(entity,"Entity must not be null");
    if(entityInformation.isNew(entity)){
    	em.persist(entity);
        return entity;
    }else{
    return em.merge(entity);
	}
}

여기 코드에서 보면
두가지 경우로 나뉘어서 보게 됩니다.

1. Version 필드가 존재하지 않는 경우

  • 상위 클래스인 AbstractEntityInformation.isNew() 를 호출하여 id필드가 null 인 0인 경우 New Entity임을 판단

2. Version 필드가 존재하는 경우

  • Version 필드 값이 null이라면 New Entity로 판단한다. Version 필드를 가진 Entity라면 Id 필드를 New Entity로 판단하는데 활용하지 않는다.

  • 처음 우리 예제에서 처음 save 이전에는 Id 와 Version필드에 값이 없는 New Entity 상태이다. 그래서 SimpleJpaRepository.class 의 save에서 em.persist를 실행한다.

  • 2번째 save에서는 id필드 (또는 Version) 에 값이 있는 Entity를 다시 save를 친다면 isNew는 false를 반환하고 em.merge()를 실행하게 된다.


  • EntityManager가 해당 Entity를 persist하면 Entity가 TRANSIENT 상태로 인식하고 Insert 구문을 실행한다.

  • EntityManager가 해당 Entity를 merge 로 Entity가 DETACHED 상태로 인식하여 Update구문이 실행된다.

그렴 persist면 insert? merge면 update? 이 구분은 hibernate의 EntityManager의 구현체 코드를 살펴봐야한다.

profile
like_learning

2개의 댓글

comment-user-thumbnail
2023년 8월 1일

와!

답글 달기
comment-user-thumbnail
2023년 9월 14일

와! 잘보고 갑니다~!!

답글 달기