2021 11 10
2021-11-10¶
댓글 삭제 로직 변경¶
- 참고: https://github.com/woowacourse-teams/2021-nolto/pull/694
- 찰리 피드백
- orphanRemoval에 의존적이였던 댓글 삭제 로직
- 서비스의 역할이
영속화 된 데이터 지운다라면 Repository로 지우는 게 맞지 않나? - Reply가 안지워지고 살아있는 이유 1. 현재 User의List<Comment>는 CascadeType.ALL 2. commentRepository.delete(comment) -> comment 상태가 removed 3. 영속성 컨텍스트가 flush 됨 4. User의 CascadeType.ALL의List<Comment>에는 아직 Comment 객체 남음 5. 결과적으로 Comment는 Persist 상태 6. 삭제쿼리 씹힘 - em.clear()의 뜻 - 참고: https://docs.oracle.com/javaee/7/api/javax/persistence/EntityManager.html - 영속성 컨텍스트를 삭제하고, 관리중이던 엔티티를 모두 detach 상태로 변경 - 새로 트랜잭션 연다고 할 수는 없음!
- 포모 피드백
- repository로 지우자 vs 객체 매핑 orphanRemoval로 지우자
- 객체를 객체답게 쓰자는 의견으로 후자 승리
- comment의 부모는 feed, user 둘 다
- persist, orphanRemoval은 정말 부모-자식 관계가 명확한 엔티티만 사용하는 것이 좋아보인다!
- 개발자가 결과 예측가능한 선에서 관계 매핑 해야지 않겠냐
- 서비스에서
@Transactional- 참고: https://javabom.tistory.com/103 - 테스트에서@Transactional로 쉽게 롤백 가능 - JPA에서는 조심해서 적용해야 해 (요런 케이스) - 서비스 코드에서는@Transactional없다면 영속성 컨텍스트 없어서 Lazy Loading 불가능 - 테스트 코드에서는@Transactional있어서 영속성 컨텍스트 있어서 Lazy Loading 가능 - 개발자의 실수로 런타임에서만 LazyInitailizationException이 발생하는 문제가 생길수 있다 - 테스트 코드에서는@Transactional어노테이션 붙이지 말고, 다음과 같은 방식은 어떨까?- 그러면 테스트코드에서 `@Transactional` 쓰지마? - `@DataJpaTest`엔 이미 붙어있기도 해 - 서비스 레이어에서 테스트하고자하는게 서비스의 코드면, `@Transactional`은 의도와 빗겨나갈 수도 있다~
Open Session In View¶
- 참고: https://ykh6242.tistory.com/102

- OSIV - 영속성 컨텍스트를 뷰까지 열어두는 기능 - 뷰까지 영속성 컨텍스트 살아있다면, 뷰에서도 지연로딩 가능
- 스프링의 OSIV - 비즈니스 계층에서 트랜잭션을 사용하는 OSIV - 영속성 컨텍스트는 사용자의 요청 시점에서 생성되지만, - 데이터를 쓰거나 수정할 수 있는 트랜잭션은 비즈니스 계층에서만 사용
- 동작 원리
1. 클라이언트 요청 들어오면, 서블릿 필터나 스프링 인터셉터에서 영속성 컨텍스트 생성
- 대신 트랜잭션 시작 X
2. 서비스 계층에서
@Transactional로 트랜잭션 시작시, 1번에서 미리 생성해둔 영속성 컨텍스트를 찾아와서 트랜잭션 시작 3. 서비스 계층 끝나면 트랜잭션 커밋하고 영속성 컨텍스트 플러쉬 - 트랜잭션은 끝나도, 영속성 컨텍스트는 생존 4. 컨트롤러와 뷰까지 영속성 컨텍스트 유지됨... 조회된 엔티티는 여전히 영속상태 5. 서블릿 필터나, 스프링 인터셉터로 돌아오면 그제야 영속성 컨텍스트 종료 - 이때 플러쉬 호출 X, 즉각 종료
- 뷰 렌더링 시 프록시 Lazy Loading - Non-transactional read 가능 - 참고: https://stackoverflow.com/questions/5982517/use-transactions-for-select-statements - SELECT 시 Transaction 불필요
- 컨트롤러/뷰에서 엔티티 수정해도 영속성 컨텍스트 변경감지 X
- 영속성 컨텍스트 변경하려면 flush 필요. 근데 OSIV 요청 끝나면 flush 호출 않고 em.close()로 영속성 컨텍스트 종료 시킴
- 강제로 em.flush() 호출하면
javax.persistence.TransactionRequiredException발생
- OSIV의 단점 - 최초 DB 커넥션 시작 시점부터 API 응답 끝날때까지 영속성 컨텍스트와 DB 커넥션 유지함 - View Template이나 API 컨트롤러에서 지연로딩 가능케 함 - 하지만 이게 DB 커넥션 리소스를 오래 들고 있는다는 뜻임 - 실시간 트래픽 중요해지면 커넥션 모자라질수도 - 그래서 끄게된다면 지연로딩을 서비스단에서 다 해주고 view 넘겨줘야함
- 실무에서 OSIV 끄기 - OSIV를 끄고, Command와 Query를 분리할 것 - OrderService: 핵심 비즈니스 로직 - OrderQueryService: 화면이나 API에 맞춘 서비스 (주로 읽기 전용 트랜잭션 사용)