Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
Tags
- chapter01
- falsePosition
- CH01
- 근구하기
- 알고리즘
- Fisher discriminant analysis
- Numerical optimization
- 1차예선
- directed graphical model
- bisection
- 스터디
- undirected graphical model
- 개발순서
- 로지스틱 회귀
- MySQL
- vector미분
- 이것이 MySQL이다
- 알고리즘대회
- chapter02
- 자바ORM표준JPA프로그래밍
- Perceptron Convergence theorem
- 5397번
- 인공지능
- 선형분류
- 선형판별분석
- 2018
- graphical models
- secant
- SCPC
- 델타 rule
Archives
- Today
- Total
computer_study
[JPA] 13. 웹 애플리케이션과 영속성 관리 본문
스프링이나 J2EE 컨테이너 환경에서 JPA가 동작하는 동작 방식을 이해한다.
1. 트랜잭션 범위의 영속성 컨텍스트
스프링이나 J2EE컨테이너 환경에서 JPA사용 시 컨테이너가 제공하는 전략을 따라야 한다.
스프링 컨테이너의 기본 전략
트랜잭션 범위의 영속성 컨텍스트 전략을 사용. (트랜잭션 시작 시 영속성 컨텍스트 생성, 트랜잭션 끝나면 영속성 컨텍스트 종료)
- 스프링에서 서비스 계층에 @Transactional을 선언해서 트랜잭션을 시작
- 이 때 AOP가 먼저 동작하게 된다.
- 메소드 종료 시 트랜잭션 커밋하며 종료된다. (이 때 JPA는 영속성 컨텍스트를 플러시하여 변경 내용을 DB에 반영)
- 예외 발생 시 플러시를 호출하지 않는다.
- 트랜잭션이 같으면 같은 영속성 컨텍스트 사용 (다르면 다른 영속성 컨텍스트 사용 (같은 엔티티 매이저를 사용하더라도))
- 이런 트랜잭션과 복잡한 멀티 스레드 상황을 컨테이너가 처리해준다.
2. 준영속 상태와 지연 로딩
- 서비스, 레포지토리 계층이 아닌 컨트롤러나 뷰 같은 프리젠테이션 계층에서는 준영속 상태.
- 변경 감지 기능이 동작하지 않는다.
- 프리젠테이션 계층에선 변경이 끝난 이후 보여주는 것에만 집중하면 되므로 동작하지 않아도 별 상관 없다.
- 지연로딩이 동작하지 않는다
- 뷰 렌더링 시 연관된 엔티티를 사용하고, 엔티티를 지연 로딩으로 설정해서 조회하는 상황
영속성 컨텍스트가 없는 준영속 상태에선 지연로딩 시도 시 예외 발생 - 해결 방법
- 뷰가 필요한 엔티티를 미리 로딩
- OSIV를 사용해서 엔티티를 항상 영속 상태로 유지
- 뷰 렌더링 시 연관된 엔티티를 사용하고, 엔티티를 지연 로딩으로 설정해서 조회하는 상황
- 변경 감지 기능이 동작하지 않는다.
뷰가 필요한 엔티티를 미리 로딩하는 방법
- 글로벌 페치 전략 수정
- 글로벌 페치 전략을 지연 로딩에서 즉시 로딩으로 변경
- @ManyToOne(fetch = FetchType.EAGER) 로 설정 가능
- 단점
- 사용하지 않는 엔티티를 로딩
- N+1문제 발생
- 연관 관계가 설정된 엔티티를 조회할 경우 조회한 데이터 수 만큼 추가로 SQL을 사용해서 조회하는 문제
- order와 member가 연관되어있을 때, 조회한 order엔티티가 10개라면 member를 조회하는 SQL도 10번 실행된다
- JPQL페치 조인으로 해결 가능(15.4.1절)
- JPQL 페치 조인
- JPQL을 호출하는 시점에 함께 로딩할 엔티티를 선택하는 방법
- 조인 명령어 마지막에 fetch를 넣어주면 된다.
- 단점
- 특정 화면에 맞춘 레포지토리 메소드가 증가할 수 있다 (프리젠테이션 계층이 접근 계층을 침범)
- 적절한 타협점을 찾아야 한다.
JPQL:
select o
from Order o
join fetch o.member
SQL:
select o.*, m.*
from Order o
join Member m on o.MEMBER_ID=m.MEMBER_ID
- 강제로 초기화
- 영속성 컨텍스트가 살아있을 때 프리젠테이션 계층이 필요한 엔티티를 강제로 초기화해서 반환하는 방법
- 프록시 객체는 실제 사용하는 시점에 초기화되므로 실제 값을 호출해버린다
- ex) order.getMember() 까지 하면 프록시 객체만 반환하지만
order.gerMember().getName()까지 해서 실제 값을 사용하는 시점에 초기화
- ex) order.getMember() 까지 하면 프록시 객체만 반환하지만
- 하이버네이트를 사용하면 initialize()메소드를 사용해서 초기화도 가능
- 뷰가 필요한 엔티티에 따라 서비스 로직을 변경해야되는 상황(프리젠테이션 계층이 서비스 계층을 침범한 것)
- 서비스 계층에서 프리젠테이션 계층을 위한 프록시 초기화 역할을 분리해야 한다 (FACADE계층이 담당)
- FACADE 계층 추가
- Facade에서 트랜잭션을 시작한다.
- 역할과 특징
- 프리젠테이션 계층과 도메인 모델 계층 간의 논리적 의존성 분리
- 프리젠테이션 계층에서 필요한 프록시 객체 초기화
- 서비스 계층을 호출해서 비즈니스 로직 실행
- 리포지토리를 직접 호출해서 뷰가 요구하는 엔티티 찾음
- 중간 계층이 하나 더 있는 것이기에 더 많은 코드를 작성해야 하는 단점이 있다 (단순히 서비스 계층을 호출하는 코드가 많을 것이다.)
준영속 상태와 지연 로딩의 문제점
위 방법을 사용한다고 해도, 준영속 상태라는 것 때문에 번거로운 것은 사실
영속성 컨텍스트를 뷰까지 열어두는 것이 가장 좋은데 이게 OSIV
3. OSIV
- 영속성 컨텍스트를 뷰까지 열어두는 방법 (뷰에서도 지연 로딩 사용이 가능하다)
- 기존 OSIV
- 요청이 들어올 때 영속성 컨텍스트를 생성해 유지하고 요청이 끝나면 트랜잭션도 끝낸다.
- 기존 OSIV 문제점
- 컨트롤러나 뷰 같은 프리젠테이션 계층이 엔티티를 변경할 수 있다
- 변경하지 못하게 하는 방법
- 엔티티를 읽기 전용 인터페이스로 제공
- 엔티티 레핑
- DTO만 반환 (단순히 데이터만 전달하는 객체 DTO를 생성해서 반환)
- 위 방법 모두 코드량이 상당히 증가하게 된다.
- 이런 요청당 트랜잭션 방식의 OSIV는 최근 거의 사용되지 않는다
- 최근에는 비즈니스 계층에서만 트랜잭션을 유지하는 방식의 OSIV를 사용 (스프링 프레임워크가 제공)
- 특징
- 요청이 들어올 때 부터 끝날 때 까지 같은 영속성 컨텍스트를 유지 (한 번 조회한 엔티티는 요청이 끝날 때 까지 영속상태 유지)
- 엔티티 수정은 트랜잭션이 있는 계층에서만 동작.(프리젠테이션 계층은 조회만 가능)
- 단점
- 같은 영속성 컨텍스트를 여러 트랜잭션이 공유
- 프리젠테이션 계층에서 엔티티 수정 후 비즈니스 로직을 수정하면 엔티티가 수정될 수 있다
- 프리젠테이션 계층에서 지연 로딩에 의한 SQL이 실행. 성능 튜닝 시 여러 계층을 확인해야한다.
- OSIV사용하면 화면 출력 시 엔티티를 유지하면서 객체 그래프를 자유롭게 탐색할 수 있다.
- 복잡한 화면을 구성할 때는 이 방법이 효과적이진 않다.
- 여러 테이블을 조인하거나, 통계 화면을 보여줄 때 엔티티로 조회하기 보단 데이터들만 조회해서 DTO로 반환하는 것이 더 좋을 수도 있다.
- 같은 JVM을 벗어난 원격 상황에서 사용할 수 없다.
- 클라이언트가 필요한 데이터를 모두 JSON으로 생성해서 반환해야 한다.
- JSON으로 생성한 API는 외부API와 내부API로 자누어진다
- 외부API
- 외부에 노출
- 한 번 정의하면 변경이 어렵다
- 엔티티는 생각보다 자주 변경되는데, 변경 시 노출하는 JSON API도 함께 변경되므로 엔티티를 직접 노출하기보단 DTO로 변환해서 노출하는 것이 안전(?)
- 내부 API
- 외부에 노출하지 않는다
- 언제든지 변경 가능
- 엔티티를 변경해도 클라이언트와 서버를 동시에 수정할 수 있기에 엔티티를 직접 노출해도 괜찮다.
- 외부API
'스터디 > 자바 ORM표준 JPA 프로그래밍' 카테고리의 다른 글
[JPA] 14. 컬렉션과 부가 기능 (0) | 2022.10.05 |
---|---|
[JPA] 12. 스프링 데이터 JPA (0) | 2022.09.26 |
[JPA]10. 객체지향 쿼리 언어 (0) | 2022.09.05 |
[JPA] 08. 프록시와 연관관계 관리 (0) | 2022.08.22 |
[JPA] 07. 고급 매핑 (0) | 2022.08.08 |
Comments