자바 ORM 표준 JPA 프로그래밍 - 기본편-7

존스노우·2022년 1월 7일
0

JPA

목록 보기
7/10

프록시

이걸 왜 ? 쓸까

멤버를 조회하는데 팀도 조회?

프록시 기초

em.find() vs em.getReference() 참조를 가져온다.

find는 데이터베이스를 통해 실제 엔티티 조회

em.getReferenc() 데이터베이스 조회를 미루는 가짜(프록시) 엔티티 객체 조회

디비에 쿼리가 안나가는대 조회가 됨?

디비에 조회는 안하지만 이값이 실제 사용되는 시점에 디비에 쿼리를 날림 (getUserName)

하이버네이트가 만든 가짜 클래스

껍데기는 같지만 안에가 텅텅 비었음. 내부에는 타겟이라는게 있지만 진짜 레퍼런스를 가리킨다.
(초기엔 Null)

프록시의 특징

실제 클래스를 상속 받아 만들어 져서 실제 클래스와 겉 모양이 같음

사용하는 입장에선 진짜 객체 ? 프록시 객체? 구분하지말고 사용하면 됨(이론상)

프록시 객체는 실제 객체의 참조(target) 보관.

프록시 객체를 호출하면 프록시 객체는 실제 객체의 메소드를 호출함.

프록시 객체의 초기화

getName 호출하면

target에 값이 없으니 영속성 컨텍스트의 요청 (진짜 가져와!)

영속성 컨텍스트는 디비에 조회 실제 엔티티를 생성해서 연결을해서 반환이 된다.

두번 조회해 하면 이미 한번 조회했기 때문에 셀렉트문이 더이상 나가지 않는다.

++

프록시 객체는 처음 사용할 때 한 번만 초기화 -> 방금처럼 두번 조회해도 초기화 안돼

프록시 객체는 초기화 할 때 객체가 실제 엔티티로 바뀌는 것 아님.
초기화 되면서 프록시 객체를 통해서 실제 엔티티에 접근이 가능한 거임.

교체 되는게 아니다 프록시는 유지가 되고 내부 타켓에만 값이 채워짐

프록시 객체는 원본 엔티티를 상속받음, 따라서 타입 체크시 주의 해야됨
(== 비교 실패 , 대신 Instance of 사용 ) 프록시를 사용할지 안할지 모르기 때문에

m1 == m2 true

m1 == m2 false

영속성 컨텍스트에 찾는 엔티티가 이미 있으면 em.getReference()를 호출해도 실제 엔티티 반환 - > (반대도 성립)
실제 프록시 든 상관없이
한 영속성 컨텍스트 안에서 가져오고 PK 가 같으면 항상 트루를 반환해줘야된다

JPA가 기본적으로 제공하는 리피터블리드 JPA 항상 한 트랙잭션안에서 같은 것을 보장해 준다.

그래서 실제 엔티티를 반환하기 때문에 트루를 반환해줌

같은 프록시 반환

em.find 해도 프록시가 반환된다.

어떻게든 JPA 트랜잭션엔아 동일성을 보장 해준다.

영속성 컨텍스트의 도움을 받을수 없는 준영속 상태일 때 프록시를 초기화하면
문제 발생 (하이버네이트는 org.hibernate.LazyInitializationException 예외)

영속성 컨텍스트가 사실 없다.. 영속성 컨텍스트의 도움을 못받으니 에러가 난다.

프록시 확인

true

즉시 로딩과 지연 로딩

다시 멤버 조회할때 팀도 조회해야되나 ?

멤버 정보만 사용하는 비즈니스 로직이라 연관관계 걸려있다 하더라도 팀조회? 손해가 아닐까

LAZY 를걸면 팀을 호출하지 않는이상 멤버 객체만 조회하는 셀렉트 문이 나간다.

밑에 팀 클래스를 불러온것 (프록시 초기화가 된건가?)
팀을 조회해서 확인해보면 프록시로 조회됨.

지연로딩으로 셋팅 되있으면 멤버만 조회하다

팀을 조회하는순간 프록시로 온다 (처음에는 프록시라 비어있음)

LAZY를 사용하는순간 멤버만 검색하다가 팀을 조회할때 그때 프록시로
요청되기 때문에 성능상 이점을 없는대.

애초에 둘다 얻고싶으면?(EAGER) 근대 이건 이미 디폴트로 걸려 있음

EAGER 사용할때 ? 셀렉트 두개 날려서 각각 가져올래? 아니면 조인되서 가져올래?

프록시와 즉시로딩 주의

가급적 지연 로딩만 사용한다(실무에선)
왜냐하면 즉시 로딩을 사용하면 예상하지 못한 SQL이 발생해서

  • JPQL 에서는 N+1 문제 (처음쿼리 1개때문에 추가 쿼리N개가 나간다.


이런방법으로 해결 가능

@ManyToOne , @OneToOne 은 기본이 즉시 로딩-> LAZY 걸어야됨
두개는 기본이 지연로딩임 (X to One 관계) OneToMany는 LAZY로 되있음

지연로딩 활용

실무에서는 다 지연로딩으로 하자..

결론 : 모든 연관관계에는 지연로딩을... 즉시로딩 사용하지말자!

영속성 전이 CASCADE

영속성 전이 : CASCADE

부모를 저장할때 자식도 같이 저장하고싶을 때
자식들도 다 persist

영속성 전이 : CASCADE - 주의

영속성 전이는 연관관계 를 매핑하는 것과 관련이 없고 -> 엔티티를 영속화 할때
연관된 엔티티도 함께 영속화 하는 편리한 때문에 사용

PERSIST는 저장 할 때만 쓸랭..

언제 써야 될까?

하나의 부모가 자식들을 관리할때.. parent - child 라이프 사이클이 유사할때
소유자가 하나일 때 다같은 소리..
ex) 게시판 첨부파일 경로 같은 것 한게시물에서 한 첨부파일만 관리 하니깐

파일이 다른 엔티티에서 관리할때 쓰면안됌.
ex) child가 다른대랑 연관관계가있으면

고아 객체

고아 객체 제거 : 부모 엔티티와 연관관계가 끈헝진 자식 엔티티를 자동으로 삭제 하는 것

딜리트 쿼리가 나가는 것..

고아 객체 - 주의 !

참조가 제거된 엔티티는 다른 곳에서 참조하지 않는 고아 객체로 보고 삭제하는 기능
참조하는 곳이 하나일 때 사용해야함!

특정 엔티티가 개인송 할 때 사용

영속성 전이 + 고아 객체 , 생명주기

실전 예쩨 5 - 연관관계 관리

profile
어제의 나보다 한걸음 더

0개의 댓글