Java/JPA

프록시, 즉시로딩 주의

amungstudy 2023. 11. 17. 18:44

JPA에서는 ==비교 대신

instance of 사용하기~(프록시객체랑 그냥 객체 == 비교하면 false나옴)

(instanceOf 연산자는 객체가 어떤 클래스인지, 어떤 클래스를 상속받았는지 확인하는데 사용하는 연산자)


/* TRUE
Member m1 = em.find(Member.class, member1.getId());
Member m2 = em.find(Member.class, member2.getId());

System.out.println("m1 == m2" + (m1.getClass() == m2.getClass()));
 */


Member m1 = em.find(Member.class, member1.getId());
Member m2 = em.getReference(Member.class, member2.getId());
//false
System.out.println("m1 == m2" + (m1.getClass() == m2.getClass()));
System.out.println("m1 == m2" + (m1 instanceof Member)); // true
System.out.println("m1 == m2" + (m2 instanceof Member)); // true

영속성컨텍스트에 찾는 이미 엔티티가 있으면 getReference해도 엔티티로 가져옴

Member m1 = em.find(Member.class, member1.getId());
System.out.println("m1 = " + m1.getClass());

Member reference = em.getReference(Member.class, member1.getId());
System.out.println("reference = " + reference.getClass());

// JPA는 영속성 컨텍스트에 있고, PK가 같은 경우 == 비교하면 true를 보장해준다.
System.out.println("a == a:"+ (m1 == reference));
// JPA는 영속성 컨텍스트에 있고, PK가 같은 경우 == 비교하면 true를 보장해준다.
System.out.println("a == a:"+ (m1 == reference));

심지어 반대로 하면 ....프록시 가져옴

Member reference = em.getReference(Member.class, member1.getId());
System.out.println("reference = " + reference.getClass());

Member m1 = em.find(Member.class, member1.getId());
System.out.println("m1 = " + m1.getClass());

// JPA는 영속성 컨텍스트에 있고, PK가 같은 경우 == 비교하면 true를 보장해준다.
System.out.println("a == a:"+ (m1 == reference));

실무시 반드시 만나는 예외가 있다...

could not initialize proxy

준영속상태에서 프록시 접근시 발생.


실무에서는 즉시로딩 쓰면 안돼!

@ManyToOne, @OneToOne은 기본이 즉시로딩 -> LAZY로 설정하기

@ManyToOne(fetch = FetchType.LAZY)

즉시 로딩(EAGER) 적용하면 예상치 못한 SQL 발생함.

문제 회피 방법

1. @ManyToOne, @OneToOne은 기본이 즉시로딩 -> LAZY로 설정

2. fetch join이용

3. entitygraph

4. 배치 size