Successfully reported this slideshow.
Your SlideShare is downloading. ×

하이버네이트의 영속성 컨텍스트와 패치 전략

Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Upcoming SlideShare
스톰 미리보기
스톰 미리보기
Loading in …3
×

Check these out next

1 of 31 Ad
Advertisement

More Related Content

Slideshows for you (20)

Similar to 하이버네이트의 영속성 컨텍스트와 패치 전략 (20)

Advertisement

Recently uploaded (20)

하이버네이트의 영속성 컨텍스트와 패치 전략

  1. 1. Hibernate 초급을 넘어서 박성재 bluehatch@gmail.com
  2. 2. 하이버네이트 요소 • 클래스 맵핑 • 연관 관계 맵핑 • 영속성 컨텍스트 • 트랜잭션 • Fetch와 2nd Cache • HQL, Criteria
  3. 3. 오늘은 이것만 • 클래스 맵핑 • 연관 관계 맵핑 • 영속성 컨텍스트 • 트랜잭션 • Fetch와 2nd Cache • HQL, Criteria
  4. 4. 영속성 생명 주기
  5. 5. 영속성 생명 주기 – 조금 더 단순하게… 비영속 객 체 (Transient) 영속 객체 (Persistent) 준영속 객 체 (Detached) get(), load() , any query
  6. 6. 영속성 생명 주기 – 객체 상태 • 비영속 객체(Transient) – new 연산자로 생성된 객체 – DB나 영속성 컨텍스트와 연관이 없다. • 영속 객체(Persistent) – DB와 동일성을 지닌 엔터티(PK 기준) – 플러시 시점에 DB에 동기화(변경 내용 자동 반영) • 준영속 객체(Detached) – 작업 단위가 완료되어 영속성 컨텍스트(세션)가 닫힘 – 재진입, 병합을 통해 영속 상태로 진입 • 삭제 객체(Removed) – DB에서 삭제됨
  7. 7. 영속성 컨텍스트(aka 세션) Database
  8. 8. 영속성 컨텍스트 특징 • 영속 객체 자동 변경 감지 • 1차 캐시 • 객체 동일성 보장(== 비교) • 트랜잭션을 지원하는 지연 쓰기 • 지연 로딩 • 일반적으로 쓰래드 단위
  9. 9. 영속성 컨텍스트 – 자동 변경 감지 • 영속 객체의 현재 스냅샷과 이전 스냅샷을 비교 • 플러시 시점에 변경된 객체를 찾아 자동 업데이 트 수행 • 동적 업데이트 설정을 (dynamicUpdate = true) 통해 변경된 컬럼만 업데이트 가능
  10. 10. 영속성 컨텍스트 – 1차 캐시 • PK로 객체 조회시 영속성 컨텍스트에서 찾아 반환 – 컨텍스트에 존재 안 할 경우만 DB 쿼리 수행 – get(), load() • 일반적인 쿼리를 수행 한 경우에도 쿼리 결과 집합은 영속성 컨텍스트와 상호 작용함 – 예) A가 이미 컨텍스트에 있는 상태에서 쿼리 결과 가 A, B, C이면 A는 컨텍스트에 이미 있는 것으로 대체 하여 결과 집합 반환. – 값만 조회하는 스칼라 쿼리 제외
  11. 11. 영속성 컨텍스트 – 1차 캐시
  12. 12. 영속성 컨텍스트 – 지연 쓰기/지연 로딩 • 하이버네이트는 DB 요청을 최대한 뒤로 미룬다. – 변경 사항을 모아 DB 요청을 최소화 – DB lock을 최대한 짧게 유지 • 지연 로딩을 통해 성능 향상 – 세션 내에서만 유효(LazyInitializationException) • update()는 준영속 객체를 컨텍스트에 재진입하는 용도이다. – 사실 reattach() 라는 이름이 더 적합 – 세션 내에서 명시적 호출이 있더라도 플러시 시점에 동작 함
  13. 13. 영속성 컨텍스트 – 플러시 • 영속성 컨텍스트의 변경 내용을 DB와 동기화 – 컨텍스트 비우는거 아님~! • 플러시 모드 : AUTO, COMMIT, MANUAL, NEVER • AUTO 모드 – Hibernate 기본 모드 – 플러시 동작 시점: 트랜잭션 커밋, 명시적인 Session.flush(), 쿼리 실행 전 • MANUAL 모드 – 트랜잭션 내에서 DB 쿼리가 많으며 컨텍스트에 대량의 인스턴스가 로딩되는 작업인 경우 MANUAL 모드 사용하자~
  14. 14. 영속성 컨텍스트 – Open Session In View 패턴 • 영속성 컨텍스트(세션)를 View까지 열어둠 • View에서 지연 로딩이 가능해짐 • OSIV vs FACADE vs DTO – OSIV를 사용하지 않으면 준영속 상태가 되기 전에 프락시 (지연 로딩 객체)를 초기화 해야 함 • 스프링 OSIV는 엔터티 수정을 트랜잭션이 동작하는 계층에서만 지원 – 초기 플러시 모드: FlushMode.MANUAL – 각 트랜잰셕 시작시 FlushMode.AUTO로 변경되며 각 트랜 잭션이 종료되면 다시 FlushMode.MANUAL로 원복
  15. 15. 트랜잭션 범위 영속성 컨텍스트 – 스프링 OSIV Filter Interceptor Controller View Service DAO 영속성 컨텍스트(세션) 생존 범위 FlushMode.MANUAL FlushMode.AUTO
  16. 16. 트랜잭션 – ACID • 원자성(Atomic) – 트랜잭션 내의 여러 작업은 모두 성공 혹은 모두 실패 • 일관성(Consistency) – 예)무결정 제약 조건 • 격리성(Isolation) – 동시에 실행하는 트랜잭션들이 서로에게 영향을 미치지 않 도록 격리되어야 함 • 지속성(Durability) – 트랜잭션이 성공적으로 끝나면 결과는 기록되어야 함
  17. 17. 트랜잭션 – 격리 수준 격리 수준 DIRTY READ NON-REPATABLE READ PHANTOM READ 커밋되지 않은 읽 기 O O O 커밋된 읽기 O O 반복 가능한 읽기 O 직렬화 • DIRTY READ: 커밋되지 않고 수정 중인 데이터를 읽는 문제 • NON-REPATABLE READ: 한 트랜잭션 내에서 같은 쿼리를 두 번 수행할 때 그 사이에 다 른 트랜잭션이 값을 수정 또는 삭제함으로써 두 쿼리의 결과가 상이하게 나타나는 비 일관 성 발생 • PHANTOM READ: 한 트랜잭션 안에서 일정 범위의 레코드를 두 번 이상 읽을 때, 첫 번째 쿼리에서 없던 레코드가 두 번째 쿼리에서 나타나는 현상. 이는 트랜잭션 도중 새로운 레코 드가 삽입되는 것을 허용하기 때문에 나타남.
  18. 18. 트랜잭션 – 격리 수준(하이버네이트 적용) 격리 수준 DIRTY READ NON-REPATABLE READ PHANTOM READ 커밋되지 않은 읽 기 O O O 커밋된 읽기(일반 적인 수준) 영속성 컨텍스트+ 버전 관리로 해결 O 반복 가능한 읽기 O 직렬화 • DIRTY READ: 커밋되지 않고 수정 중인 데이터를 읽는 문제 • NON-REPATABLE READ: 한 트랜잭션 내에서 같은 쿼리를 두 번 수행할 때 그 사이에 다 른 트랜잭션이 값을 수정 또는 삭제함으로써 두 쿼리의 결과가 상이하게 나타나는 비 일관 성 발생 • PHANTOM READ: 한 트랜잭션 안에서 일정 범위의 레코드를 두 번 이상 읽을 때, 첫 번째 쿼리에서 없던 레코드가 두 번째 쿼리에서 나타나는 현상. 이는 트랜잭션 도중 새로운 레코 드가 삽입되는 것을 허용하기 때문에 나타남.
  19. 19. 트랜잭션 - 낙관적 락, 비관적 락 • 낙관적 락 – 어플리케이션(하이버네이트)에서 제공하는 락 – @Version -> 최초 커밋만 인정하기 두 번째부터 예외 를 던짐 • 비관적 락 – Database lock을 사용 – select for update
  20. 20. 트랜잭션 – 경계 설정 • 프로그래밍 방식 – 스프링 TransactionTemplate 사용 – 정교하게 경계를 나눌 때 사용 • 선언적 – @Transactional(메소드 단위) – AOP – 일반적인 방법
  21. 21. 트랜잭션 – 예외처리하기 • @Transactional 메소드 외부로 예외가 던져지면 롤백 수행 • 메소드 콜 트리에서 중첩된 @Transactional 중 예외가 밖으로 던져질 경우에도 롤백 수행 • 트랜잭션 롤백 예외 – rollbackFor, rollbackForClassName – noRollbackFor, noRollbackForClassName
  22. 22. 트랜잭션 – 스프링에서 제공하는 트랜잭션 전파 속성 • REQUIRED – 기본 속성이며 대부분 이 속성이면 충분함 – 이미 시작된 트랜잭션 이 있으면 참여하고 없 으면 새로 시작 • REQUIRES_NEW – 항상 새로운 트랜잭션 을 시작 – 이미 진행 중인 트랜잭 션이 있으면 잠시 보류 시킴 – 사용 예) 권한 체크, 감 사 로깅 • SUPPORTS, MANDATORY, NOT_SUPPORTED, NEVER, NESTED
  23. 23. N+1 문제 member -id -name … orders -id -member_id … 1 * -- get all of the member first select * from member -- get the orders for each member returned select * from orders where member_id = 1 select * from orders where member_id = 2 select * from orders where member_id = 3 select * from orders where member_id = … select * from orders where member_id = N
  24. 24. 페치 전략 • Select 페치 – 연관된 인스턴스나 콜렉션을 하나씩 SELECT 실행 • Join 페치 – SELECT 절에서 OUTER JOIN으로 한번에 쿼리 – 중복 제거를 위해 distinct 필요 • Subselect 페치 – 이전 쿼리 조건을 sub query조건에 추가하여 SELECT 실행 – 맵핑시 결정: @Fetch(FetchMode.SUBSELECT) • Batch 페치 – select fetching의 최적화 전략 – PK또는 FK 목록을 통해 하나의 SELECT절로 묶어서 쿼리 – 맵핑시 결정: @BatchSize(size=10)
  25. 25. N+1 문제 – 조인을 이용한 즉시 페치 -- HQL select distinct m from Member m join fetch m.orders -- 실행된 SQL SELECT DISTINCT M.*, O.* FROM MEMBER M INNJER JOIN ORDERS O ON M.ID = O.MEMBER_ID -> distinct 옵션 적용 시 하이버네이트는 SQL에 DISTINCT 적용과 함께 결과 리스트에세 Member객체를 중복 제거 함 -> 컬렉션을 두 개 이상 조인 페치할 경우 카테시안 곱 (Cartesian Product) 발생함
  26. 26. N+1 문제 – Subselect 페치 -- HQL select m from Member m where m.id > 10 -- 지연 로딩된 엔터티를 사용하는 시점의 SQL 실행문 SELECT O.* FROM ORDERS O WHERE O.MEMBER_ID IN ( SELECT M.ID FROM MEMBER M WHERE M.ID > 10 )
  27. 27. N+1 문제 – Batch로 데이터 선행 페치 -- HQL select m from Member … -- 지연 로딩된 엔터티를 사용하는 시점의 SQL 실행문 (BatchSize개수 만큼 로딩하는 쿼리를 여러 번 수행) SELECT O.* FROM ORDERS O WHERE O.MEMBER_ID IN (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)

×