프로젝트/개인 프로젝트(2023.11.13-2023.12.18)

[개인프로젝트] CascadeType 미설정 오류

dal_been 2023. 12. 17. 22:44
728x90

나는야 바보...하하하하하 앞서 블로그내용에서 WalkerReserveServiceInfo, PayHistory 를 연관관계를 변경하면서 지금까지 작성했던 모든 테스트를 돌려봤는데 여디선가 뭔가 에러가...

그 에러는 사실 너무 간단한거라서.. 패스.. 대충 얘기하자면 PayHistory부터 저장하고 WalkerReserveServiceInfo에 저장했어야했는데 전의 코드가 반영되어있던 터라 WalkerReserveServiceInfo의 PayHistory필드에 null이 들어간 오류였다.. 이건 너무 심플해서 패스..

 

 

문제상황

 

일단 나는 예약요청이 들어왔는데 10분안에 예약수행자가 수락/거절 을 하지않으면 자동으로 거절되는 기능을 구현했다. 스프링 배치를 이용해서

 

그래서 WalkerReserveServiceInfo status 필드 상태와 PayHistory status필드 상태를 바꿔야했다. 예를 들어 REFUND로

근데 이상하게 PayHistory상태가 계속 안바뀌는 거다...

 

  @Bean
  public JpaPagingItemReader<WalkerReserveServiceInfo> reserveReader(){
    Map<String, Object> parameter=new HashMap<>();
    parameter.put("createdAt", LocalDateTime.now().minusMinutes(10));
    parameter.put("status", WALKER_CHECKING);
    return new JpaPagingItemReaderBuilder<WalkerReserveServiceInfo>()
        .name("reserveReader")
        .entityManagerFactory(entityManagerFactory)
        .pageSize(chunkSize)
        .queryString("SELECT w FROM WalkerReserveServiceInfo w "
            + "Join Fetch w.payHistory p "
            + "WHERE w.createdAt < :createdAt "
            + "AND w.status = :status")
        .parameterValues(parameter)
        .build();
  }
  
  @Bean
  @Transactional
  public ItemProcessor<WalkerReserveServiceInfo,WalkerReserveServiceInfo> reserveProcessor(){
    return reserveService -> {
      reserveService.setStatus(WALKER_REFUSE);
      reserveService.getPayHistory().setPayStatus(PAY_REFUND);
      return entityManagerFactory.createEntityManager().merge(reserveService);
    };
  }

 

코드 일부분을 가져왔다.

그래서 쿼리를 보면...

 

    update
        com.project.dogwalker.domain.reserve.WalkerReserveServiceInfo */ update walker_reserve_service 
    set
        walker_reserve_service_created_at=?,
        customer_id=?,
        pay_history_id=?,
        walker_service_date=?,
        walker_reserve_service_price=?,
        walker_service_status=?,
        walker_service_time_unit=?,
        walker_reserve_service_updated_at=?,
        walker_id=? 
    where
        walker_reserve_service_id=?

 

WalkerReserveServiceInfo만 업데이트가 되는 것이다...

왜..??

 

일단 PayHistory는 lazy로딩 가능하다. 스프링 배치에서 그리고 log를 찍어보면 payhistory값이 나온다..

왜일까??를 한 3시간 고민하고 30분정도 쉬다가 갑자기 떠올랐다..

 

해결상황

 

그의 이름 cascadeType....

아 jpa 공부를 너무 오래안했어.. 개념 다 까먹음..이러면 안되...

 

일단 WalkerReserveServiceInfo부분에 코드를 이렇게 수정했다

 

  @OneToOne(fetch = FetchType.LAZY,cascade = CascadeType.MERGE)
  @JoinColumn(name = "pay_history_id")
  private PayHistory payHistory;

 

이러고 테스트 돌려보면 

 

2023-12-17T22:33:15.007+09:00 DEBUG 16736 --- [           main] org.hibernate.SQL                        : 
     update
        com.project.dogwalker.domain.reserve.PayHistory */ update pay_history 
    set
        pay_created_at=?,
        user_id=?,
        pay_method=?,
        pay_price=?,
        pay_status=?,
        pay_updated_at=? 
    where
        pay_history_id=?
2023-12-17T22:33:15.008+09:00 DEBUG 16736 --- [           main] org.hibernate.SQL                        : 
     update
        com.project.dogwalker.domain.reserve.WalkerReserveServiceInfo */ update walker_reserve_service 
    set
        walker_reserve_service_created_at=?,
        customer_id=?,
        pay_history_id=?,
        walker_service_date=?,
        walker_reserve_service_price=?,
        walker_service_status=?,
        walker_service_time_unit=?,
        walker_reserve_service_updated_at=?,
        walker_id=? 
    where
        walker_reserve_service_id=?

 

네 아주 이쁘게 잘 나가쥬??

 

근데 cascadeType persist로 하면 안되나?? 

org.springframework.dao.InvalidDataAccessApiUsageException: 
detached entity passed to persist: com.project.dogwalker.domain.reserve.PayHistory

 

Persist로 하고 돌려봤더니 detached!!

즉 이미 영속성 컨텍스트에서 분리된 엔티티를 persist할때 발생하는 에러다.

지금 내 스프링 배치는 reader,processor,writer가 각각의 영속성컨텍스트에서 조회하고 있다(이유는 아직 모름..나중에 알아보자)

 

그러다보니 PayHistory detached된 상태이기에 persist는 불가능하다.

 


진짜 이거 에러 보고 심장이 벌렁거렸다. 이전 N+1문제 해결하겠다고 코드 만진게 다른 에러를 불러와서..아 괜히...아니아니아니아ㅣㄴ아니야!! 잘한거야 앞으로도 이렇게 찾아보면 되지...ㅎㅎㅎ