3. 1. JPA basic concepts
( from Pro JPA2, 2nd Edition )
4. 1. JPA basic concepts
a. Persistence : bootstrap class used to obtain an entityManagerFactory
5. 1. JPA basic concepts
b. EntityManagerFactory
- EntityManager를 가져오기 위한 객체
- SpringFramework 에서는 이미 다양한 EntityManagerFactoryBean 을 제공한다.
- EntityManagerFactory는 Persistence Unit을 필수로 요한다.
- EntityManagerFactory는 생성비용이 커서 대개 한번만 생성하고 공유해서 사용한다.
6. 1. JPA basic concepts
c. Persistence Unit
- Named configuration declaring the entity classes and data store info
- SpringBoot 에서는 properties 읽어서 자동으로 설정 가능.
- persistence.xml 에 기술한다.
7. 1. JPA basic concepts
d. EntityManager
- Jpa 명세 대부분의 구현을 담당한다.
- @PersistenceContext ( 스프링에서는 대략 이런 방식으로 .. 실제는 훨씬 더 복잡한 케이스와 과정이 있다.)
8. 1. JPA basic concepts
d. Persistence Context
- EntityManager가 PersistenceContext를 이용해 entity의 영속성 관리를 한다.
< Entity Lifecycle, 100번 강조해도 지나치지 않다. >
- 1차 캐시, 동일성 보장, 변경 감지
9. 2. Entity Manager
a. Flush : 데이터베이스에 반영하는 것을 flushing 이라고 한다.
- 강제 Flush : entityManager.flush()
- 트랜잭션 commit
- 쿼리 실행 전 영속성 컨텍스트의 상태가 쿼리 결과에 영향을 미친다고 판단 되는 경우
- FlushMode를 설정으로 변경 가능 하다. ( Always, Auto, Commit, Manual )
Q. FulshMode.Auto 상태에서 SpringDataJpa 를 사용 할때 언제 플러쉬 될까 ?
- Entity entityA = repositoryA.save(entityA)
- entityA.setAttributeX(‘Y’);
- entityA = repositoryA.save(entityA);
JPA 구현체 별로 그 판단이 상이한 경우도 있을수 있다.
10. 2. Entity Manager
b. Detached : entity가 persistent 상태를 벗어난 상태
- detach : entityManager.detach(entity)
- context clear : entityManager.clear()
- session 종료( close )
Persistent 상태의 Entity가 Detached 상태로
전이 하는 단계는 Transaction 이 끝나는 시점이 아닌
Session이 Close 되는 시점 !!
12. 3. Lazy Load
a. Proxy Object
- What is difference? (in Spring Data JPA )
repository.getOne(Pk id);
repository.findOne(Pk id);
repository.findById(Pk id);
https://docs.spring.io/spring-data/data-jpa/docs/current/api/
- Spring Data Jpa JavaDoc
14. 4. OSIV
a. What is OSIV ( Open Session In View )
: 뷰 렌더링 시점 까지 영속성 컨텍스트를 오픈한 채로 유지 하는것
( To avoid the LazyInitializationException )
DB Connection ? DB Flush ? Transaction ?
Detached ? Commit ?
When ?
15. 4. OSIV
b. Using Servlet Filter
==> DB Flush, Release Connection, Detached State
문제점 : 모호한 트랜잭션 경계, DB 커넥션 보유 시간 증가
16. 4. OSIV
c. How to use in Spring Framework
- OpenSessionInVewFilter
- OpenSessionInViewInterceptor
1. Session Open -> FlushMode.MANUAL
2. Save currentSession into ThreadLocal ( to use single session )
3. @Transactional
- Get single session from ThreadLocal & change FlushMode.AUTO
- Get Connection, begin Tx
- Execute Tx
- Commit ( Flush ) or Rollback
- Release Connection
- Change FlushMode.MANUAL
4. LazyLoad
@Transactional 영역 밖의 의도하지 않은 변경도 함께 Flush
- Get Connection ( auto commit mode )
- Execute & Release Connection
5. Session close ( change detached state )
18. 4. OSIV
d. How to use in SpringBoot
- open-in-view : true ( default option )
( From https://terasolunaorg.github.io )
19. 4. OSIV
e. Is it Anti-Pattern?
- Transaction 유지 시간 ( 전통적 서블릿 필터 방식 )
- 모호한 Transaction 경계 (전통적 서블릿 필터 방식)
- 의도치 않은 데이터의 수정 ( until session close )
- 메모리 문제로 인한 성능저하 or OOM Exception
- 인지하지 못한 Query 수행 (ex: N+1 Query )
OSIV 패턴을 제대로 사용 하려면 …
- 서비스 내에서 실행되는 모든 query 모니터링
- 개발팀 전원이 JPA 및 OSIV 패턴을 제대로 이해 하고 있어야한다.
어느정도 규모가 큰 회사라면 … (개인적인 의견 이지만 … )
개발자 전원을 컨트롤 할수 없다면 ..
OSIV 패턴을 사용하지 못하게 강제화 하는게 낫지 않을까 ?
21. 4. OSIV
g. More details ..
http://pds19.egloos.com/pds/201106/28/18/Open_Session_In_View_Pattern.pdf
http://aeternum.egloos.com/2798098
22. 5. Anti-Patterns
a. OneToMany 단방향
Company - Branch 1:N 관계에서 조인의 주체는 Branch 이다.
즉, Branch 에서 @ManyToOne 매핑을 하면서 companyId를 조인컬럼으로 사용 한다.
- 나는 oneToMany 단방향만 있으면 돼 !
별도의 매핑 테이블이 자동으로 생성 되거나 ,,,
Insert 할때 의도하지 않은 Update 쿼리가 실행 되기도 한다.
( 의도적으로 OneToMany에 JoinColumn을 지정하는 경우도 있긴 하지만 ,,, )
23. 5. Anti-Patterns
b. Batch task
영속성 관리 상태 에서 ( Persistence Context 내에서 )
Entity를 과도하게 조회 할때 ( ex: Excel Download )
24. 5. Anti-Patterns
c. OneToMany Outer Join
기대한 내용은 ..
기대한 결과 대로 잘 실행 되었지만 ,,,
HHH000104: firstResult/maxResults specified with collection fetch
Limit 조건이 적용되지 않았고 조건에 맞는 전체 데이터를 조회한 후 메모리 에서 필요한 만큼 결과를 추출해 준다.
이런건 아예 실행 조차 되지 않도록 … -_-
좀 더 엄격한 규칙이 반영된 JPA 구현체가 있으면 정말 좋겠다.
25. 5. Anti-Patterns
d. N+1 Query
OSIV 설정이 되어 있다면 …
View 렌더링 시점에 DB Connection N번 가져와서 Query N번 실행