[ JPA ] 영속성 컨텍스트로 인해 Update 가 되지 않을 때

5tr1ker·2024년 11월 29일
0

JPA

목록 보기
4/4
post-thumbnail

매장에 대해 추천 메뉴를 재설정하는 로직을 작성할 때 오류가 발생했습니다..
update 쿼리 실행 후, select 조회 후 값을 변경 하였지만, 값이 변경되지 않았습니다. ( 변경 감지 안됨 )

@Transactional
   public void updateRecommendationSideMenu(long marketId, List<Long> menuId) {
       menuRepository.resetRecommendSideMenu(marketId);

       List<Menu> menus = marketRepository.findMarketMenuById(marketId, menuId);
       for(Menu menu : menus) {
           menu.setRecommendSideMenu();
       }
   }

위의 로직은 다음과 같이 진행됩니다.
추천 사이드 메뉴 제거 > 메뉴 검색 > 해당 메뉴를 추천 사이드 메뉴로 설정

로그 발생

로그에서는 첫 번째 update문이 잘 실행되고 있었습니다. 이후 for 문 안에 수정 대상이 되는 엔티티가 정상적으로 순회가 되고 있었으나, 특정 엔티티는 update 문이 실행되지 않는 문제를 확인했습니다.

문제 해결 과정

find를 통해서 데이터가 조회되지 않는가..?

for문을 통해 데이터를 모두 출력했을 땐 모든 데이터가 잘 조회되는 것 같다..

로그를 통해 update가 잘 되는가?

로그를 확인해 봤을 때 특정 엔티티가 update되지 않았다. find 메서드를 통해 조회는 되지만 update가 실행되지 않는데, 이유는 다음과 같은 가설을 세울 수 있습니다.

  1. 영속성 컨텍스트에 있는 엔티티는 최신 상태가 아닐 수 있다. ( 1차 캐시 )
    1.1 왜? update, delete 문은 영속성 컨텍스트를 무시하고 바로 DB에 반영하기 때문입니다.
  2. 영속성 컨텍스트에 있는 엔티티는 바뀌기 전 값이기 때문에 스냅샷과 엔티티가 같은 값을 가지기에 변경 감지가 동작하지 않는다.
  3. 그렇다면 영속성 컨텍스트를 초기화 해볼까?

    entityManager.clear();
    를 통해서 영속성 컨텍스트를 초기화 해보자
    문제가 해결이 되었다.

나는 조회한 적이 없는데 왜 영속성 컨텍스트에 들어가 있지..?

  @Override
    public long resetRecommendSideMenu(long marketId) {
        List<Menu> menus = jpaQueryFactory.select(menu)
                .from(market)
                .innerJoin(market.menuContainers, menuContainer)
                .innerJoin(menuContainer.menus, menu)
                .where(market.marketId.eq(marketId))
                .fetch();

        return jpaQueryFactory.update(menu).set(menu.isRecommendSideMenu, false)
                .where(menu.in(menus))
                .execute();
    }

영속성 컨텍스트에 들어가 있는 이유는 저 위의 이유입니다..
처음 메뉴를 초기화 하는 과정에서 select 문을 통해 모든 menu를 조회했기 때문에 영속성 컨텍스트에 해당 엔티티가 들어가있습니다.

결론

JPA에 대해서 기본 이해가 없었다면 절대로 풀지 못했을 것이였다..
영속성 컨텍스트의 특징과 메서드를 잘 알고 있지 않았다면 많은 삽질을 했을 것이다.

profile
https://github.com/5tr1ker

0개의 댓글