BankSystem, 2022년 1월 11일

yshjft·2022년 1월 11일
0

Bank System

목록 보기
7/14

RequestContextHolder

HttpServletRequest

controller에서 많이 사용 for cookie 확인, session 사용(for 로그인). 하지만 HttpServletRequest에 대한 접근은 servlet, filter, interceptor, AOP, controller에서만 허용됨.

만약 service에서 사용을 원한다면

VO를 이용하여 controller에서 service로 전달 OR RequestContextHeader

RequestContextHolder

어디에서든 HttpServletRequest에 접근할 수 있도록 한다. 아래와 같이 RequestContextListener를 Bean으로 등록한 후 사용하면 된다.

@Bean
public RequestContextListener requestContextListener(){
return new RequestContextListener();
}

....

HttpServletRequest req = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();

unit test에서의 경우

MockHttpServletRequest request = new MockHttpServletRequest();
RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(request));

Spring Data JPA

영속성 전이

영속성 전이란 특정 엔티티를 영속 상태로 만들 때 연관된 엔티티도 함께 영속 상태로 만들 때 사용한다. 나 또한 이를 개인 프로젝트에 적용하였다.

@OneToMany(mappedBy = "account", cascade = CascadeType.ALL)

ALL을 이용하여 저장시와 삭제시 모두 영속성 전이가 이루어질 수 있도록 하였다. 저장시에는 문제가 없었지만 삭제시에 문제가 발생하였다. one에 해당하는 데이터가 삭제될 때 many에 있는 데이터가 벌크로 삭제될 것을 예상하였지만 데이터 별로 delete query가 따로따로 나가고 있었다.

벌크 연산

찾아보니 Spring Data Jpa는 벌크 삭제 또는 수정을 기본적으로 지원하지 않는다고 한다. 벌크로 수정 또는 삭제를 하기 위해서는 @Modifying이라는 어노테이션을 적용해야 한다. 이 때 주의해야 할것은 벌크 연산은 영속성 컨텍스트를 무시하고 실행하기 때문에 영속성 컨텍스트에 엔티티가 없는 상태에서 벌크 연산을 먼저 실행하거나 벌크 연산 직후 영속성 컨텍스트를 초기화 해야 한다. 따라서 나는 아래와 같이 영속성 전이는 저장시에만 사용하고 삭제 시에는 직접 벌크 삭제를 할 수 있도록 수정하였다.

@OneToMany(mappedBy = "account", cascade = CascadeType.PERSIST)

...

@Modifying(flushAutomatically = true, clearAutomatically = true)
@Query("delete from AccountLog acl where acl.account.id = :accountId")
void bulkDeleteByAccount(@Param("accountId") Long accountId);
  • flushAutomatically
    수정 쿼리를 실행 전에 영속성 컨텍스트를 flush()한다.

  • clearAutomatically
    수정 쿼리를 실행 후 영속성 컨텍스트를 초기화(clear())한다.

  • 보충)

    • JPQL 실행시 flush() 발생
      JPA에서는 JPQL 실행시 flush()를 강제로 발생시키는 기본 모드로 사용하고 있다. 이 덕분에 Spring Data JPA에서 @Modifying이라는 어노테이션의 flushAutomatically 라는 옵션을 false로 하고도 DB에 데이터가 반영되어 있어 아무 문제가 발생하지 않게 된 것이다.

    • 그렇다면 @Modifying에서 flushAutomatically라는 옵션은 왜 필요한 것일까?
      JPQL 실행시 강제로 flush()가 발생한다면 flushAutomatically라는 옵션은 불필요한 것이 아닐까라는 생각이 들었다. 하지만 JPQL 실행시 flush()가 발생하는 것에 대하여 좀 더 정확히 말하면 JPQL과 관련 있는 엔티티에 대해서만 flush()를 하는 것이고 flush() 강제 옵션 또한 사용하지 않도록 설정할 수 있기에 flushAutomatically라는 옵션은 필요하다고 한다.

      flushAutomatically옵션에 대하여

참고

profile
꾸준히 나아가자 🐢

0개의 댓글