위 그림처럼 JPA Repository는 분명 interface만 정의해줬다. 구현체를 내가 따로 만든게 없다.

그런데 위 그림처럼 사용하는쪽에서 해당 Repository를 D.I를해서 사용할 수 있다. 구현체를 알아서 스프링에서 만들어주니, 쓸수 있는거일텐데..

도대체 Repository 구현체는 어떤과정에 의해서 만들어지는것인가..?

 

디버깅을 통한 결과이다.

 

JpaRepositoryFactoryBean -> JpaRepositoryFactory -> interface (ex.PaymentRepository)를 가지고 reflection implement를 실행 -> SimpleJpaRepositoryImpl

그리고 Repository가 저렇게 JpaRepositoryFactory에서 생성이 되는 전제조건은 Repository를 스캔하는 base package를 설정해놔야 한다.
이전에 @Component, @Service , @Bean 들은 두개의 스캔과정을 가지고 있다는것을 알게 됐다.

1) @ComponentScan 2) EnableAutoConfigureScan 

@Repository는 위 2가지 스캔 과정과 별개로 다른 스캔 과정, 어노테이션이 필요하다! 

@SpringBootApplication이 붙은 메인클래스에 Repository는 @EnableJpaRepositories 어노테이션으로 설정이 가능하다. 저렇게 하면 basepackage가 com.waug.auth.common.rememberme.repository가 된다. 설정을 안하면 디폴트로 main 아래 java 패키지이다.

 

 

 

일단 크게 2가지가 있다.

1. @HandlerException, @ControllerAdvice를 이용하는 방안

2. BasicErrorController를 이용하는 방안

 

이 두 사용방안은 실행되는 위치가 다르다. 

1은 Interceptor, 2는 Filter

그림으로 보면,

1 에서 처리된 exception은 2까지 전파되지 않는다. 그래서 중복설정하게되면 basicErrorController가 왜 먹히지?하는 상황이 올수있다. 1과 2의 공통기능은 결국 Exception을 핸들링해주는 것이기 때문에 각 특징을 알고 써먹으면 될거같다.

 

@HandlerException와 BasicErrorController의 각각의 특징을 정리해보면,,

 

- HandlerException

 Exception을 미리 메소드별로 나눠서 처리가능하다. 반대로 말하면 BasicErrorController는 모든 exception을 메소드별로 나눠서 처리하는게 불가능(error(), errorHtml()이란 메소드로만 분리됨)

 

- BasicErrorController

Exception을 html로 주는 경우(errorHtml), 그 외의 경우로 나눌수(error) 있음

 

 

 

 

'개발 > Spring' 카테고리의 다른 글

JPA Repository의 D.I 과정  (0) 2020.06.25
Transaction & 영속성 컨텍스트 이야기  (0) 2020.06.23
  • 트랜잭션 범위의 영속성 컨텍스트 전략이 기본이다

  • 트랜잭션범위(=영속성 컨텍스트 범)에 있지않는 뷰 레벨(컨트롤러 등)에서 엔티티에 접근을 하다가 LazyInitailize Exception 이 발생!

  • 원인 사례 : 

    • " 어 나는 뷰에는 이 엔티티의 필드를 좀 암호화해서 넘기구싶어" 것을 원할수가 있음

    • " 뷰 레벨에서 나중에 (Lazy) 꺼내 써야지~ 지금은 당장 필요없으니깐~"

  • Lazy InitializeException을 해결하는 방법이 뭐가 있을까?

    • 뷰 레벨전에 엔티티를 미리 초기화하는 방법이 있겠네

      • 그럼 뷰 레벨전에 엔티티를 초기화하는 방법엔 뭐가있을까?

        • 글로벌 페치 전략 수정

          • Entity에 fetchType Eager로 지정

          • 사용하지 않을수도있는 엔티티 까지도 로딩해서 메모리 문제.. 여기까진 OK

          • 일반 JPA 메소드로 조회했을떄는 이너조인해서 잘 가져온다 문제가없다.. 근데? JPQL을 사용하게 되면 N+1 문제가 발생한다

        • JPQL 페치 조인

          • 위의 N+1문제를 해결하기 위해 JPQL을 쓸때는 페치 조인을 쓴다. 

        • 강제로 초기화(Facade)

          • 이것도 아니면 Lazy 로딩인걸 무조건 initialize하는 계층인 facade 계층을 하나 만든다.(Controller <-> facade <-> service)

    • 뷰 레벨전에 엔티티를 미리 초기화의 문제점

      • 누가 뷰 만들때 이 엔티티가 초기화 잘됐는지까지 확인해.. 그냥 뷰만 딱 만들지..너무 모델뷰간의 의존성이 높아진다..

    • 그러면 Lazy InitializeException 가장 좋은방법은 OSIV 적용!

      • 스프링의 예전 OSIV

        • 요청당 트랜잭션 방식의 OSIV , 즉 요청이 들어오는 즉시(필터/인터셉터부터) 트랜잭션 시작!  영속성컨텍스트도 똑같이 시작!

          • 문제점 : 뷰레벨에서 모델에 셋을할수있음. 즉 데이터가 바뀔수있음 뷰레벨에서.

      • 지금의 스프링 OSIV

        • 서비스단에서 트랜잭션 시작!  영속성컨텍스트는 필터/인터셉터부터 시작

+ Recent posts