Open Session In View
의 약자DB커넥션
에 대한세션
을View까지 유지하는 것
에 대한전략
기본값
은true
- 부르는
명칭
이 조금씩 다르지만,관례
상OSIV
라고 부름
Hibernate
:OSIV(Open Session In View)
JPA
:OEIV(Open EntityManage In View)
- 우리는
jpa
에서 적용하는sping.jpa.open-in-view
속성에 대해 다룰 것
sping.jpa.open-in-view : true
DB 커넥션
을사용자의 요청
이끝날 때 까지 계속 유지
- 장점
DB 커넥션
을계속 유지
한다는 것은영속성 컨텍스트
의생존범위
가확장
되는 것!
--> 그래서연관관계
LAZY fetch 전략
을서비스를 벗어난 곳
에서사용 가능!
- 단점
- 너무
오랜시간
동안DB 커넥션을 유지
하여리소스를 사용
하기 때문에실시간 트래픽이 중요한 Application
에서는DB 커넥션
이모자랄 수 있음
(장애 발생
)
sping.jpa.open-in-view : false
DB 커넥션
을Transaction 내부까지만 유지
(Transaction
은Service
에서수행
되니까Service까지만 유지
되는 것)
- 장점
DB 커넥션 리소스
의효율적인 사용
:트랜잭션을 종료
할 때영속성 컨텍스트
를 닫으면서DB 커넥션
을반환
- 단점
모든 지연로딩
을트랜잭션 안에서 처리
:지연로딩에 관한 모든 로직
을Service
/Repository
에서해결
해야 함
OSIV 전략
을false
로 둔 상태에서복잡성을 관리하는 방법
들이 존재
1)Command와 Query를 분리
2)Service / Repotisotry 에서 모든 지연로딩을 처리
Command
와Query
를분리
하는 방법 (김영한님 선호
)
:Controller
에서지연로딩
을 처리해야 할 때Query용 Service
를 만드는 것OrderService
OrderService
:핵심 비즈니스 로직
OrderQueryService
:화면
이나API
에맞춘 서비스
(주로읽기 전용 트랜잭션
)
OSIV
는DB 커넥션 리소스
에 대한효율적인 사용
과 관련된전략
OSIV 실무 조언
고객 서비스의 실시간 API
:OSIV
false
설정ADMIN 처럼 커넥션이 많지 않은 곳
:OSIV
true
설정
- 해결방안
Service
/Repository
에서지연로딩
을처리
하는 것이너무 많아지고 복잡
해지면파일로 따로 분리
JPA
를 사용할 때 지루하게반복되는 코드
를자동화
: 여러도메인
마다save
,findById
이런것은반복
되는 경우가 많다JpaRepository
라는인터페이스를 제공
하며 이것을상속
받는 것 하나로기능 제공
:기본적인 CRUD기능
과다양한 것
들이 만들어져 있음findByName
처럼특정 필드
에 관한 것들도정해진 메서드 이름
으로 만들면알아서 수행
개발자
는인터페이스
만만들면
된다
-->스프링 데이터 JPA
가애플리케이션 실행시점
에구현체
를 만들어서알아서 주입!
개발 생산성
의 놀라운확장 가능
-->실무
에서필수적으로 사용
JPQL
만으로는 힘든동적쿼리를 사용
하기 쉽게 제공하는오픈소스 라이브러리
QueryDSL은 SQL(JPQL)
과유사
하여자바코드
로동적 쿼리
를 편리하게 생성
- 장점
직관
적인문법
컴파일 시점
에 빠른문법 오류 발견
코드 자동완성
코드 재사용
JPQL new 명령어
와는 비교가 안될정도로 깔끔한DTO조회 지원
( build.gradle 추가 )
/* Quyery DSL */ buildscript { dependencies { classpath("gradle.plugin.com.ewerk.gradle.plugins:querydsl-plugin:1.0.10") } } ... /* Quyery DSL */ apply plugin: "com.ewerk.gradle.plugins.querydsl" ... dependencies { /* Query DSL */ implementation 'com.querydsl:querydsl-jpa' implementation 'com.querydsl:querydsl-apt' } ... //querydsl 추가 //def querydslDir = 'src/main/generated' def querydslDir = "$buildDir/generated/querydsl" querydsl { library = "com.querydsl:querydsl-apt" jpa = true querydslSourcesDir = querydslDir } sourceSets { main { java { srcDirs = ['src/main/java', querydslDir] } } } compileQuerydsl{ options.annotationProcessorPath = configurations.querydsl } configurations { querydsl.extendsFrom compileClasspath }
( compile 실행 )
( 만들어진 파일 )