JPA PROXY

XingXiΒ·2024λ…„ 1μ›” 3일
0

JPA

λͺ©λ‘ 보기
15/23
post-thumbnail

πŸ• Reference

μžλ°” ORM ν‘œμ€€ JPA ν”„λ‘œκ·Έλž˜λ° : ꡐ보문고
μžλ°” ORM ν‘œμ€€ JPA ν”„λ‘œκ·Έλž˜λ° - 기본편 : μΈν”„λŸ°

JPA Proxy

μ‹€μ œ Entity λŒ€μ‹  DB 쑰회λ₯Ό 지연할 수 μžˆλŠ” 객체λ₯Ό λ§ν•œλ‹€.

Proxy 객체


proxy κ°μ²΄λŠ” μ‹€μ œ Entity λ₯Ό 상속 λ°›μ•„μ„œ λ§Œλ“€μ–΄μ§„ 객체이닀.
μ‚¬μš©μž μž…μž₯μ—μ„œ Entity 인지 Proxy 객체인지 κ΅¬λΆ„ν•˜μ§€ λͺ»ν•œλ‹€.
Proxy κ°μ²΄λŠ” μ‹€μ œ 객체 μ°Έμ‘°λ₯Ό λ³΄κ΄€ν•˜λŠ”λ° 처음 Proxy 객체가 μƒμ„±λ˜λ©΄ null 이 ν• λ‹Ήλœλ‹€.
μ‚¬μš©μžλ₯Ό λŒ€μ‹ ν•˜μ—¬ Entity 의 Method ν˜ΈμΆœν•œλ‹€.

SUMMARY
1. proxy κ°μ²΄λŠ” μ‹€μ œ Entity λ₯Ό 상속 λ°›μ•„μ„œ λ§Œλ“€μ–΄μ§„ 객체
2. μ‹€μ œ 객체λ₯Ό μ°Έμ‘°ν•˜μ—¬ λ³΄κ΄€ν•˜λ©° 처음 μƒμ„±μ‹œ null ν• λ‹Ή
3. Entity 의 method κ°€ 호좜되면 Proxy 객체에 μ‹€μ œ 객체의 μ°Έμ‘°λ₯Ό 보관
4. μ‚¬μš©μžλ₯Ό λŒ€μ‹ ν•˜μ—¬ μ‹€μ œ 객체의 λ©”μ†Œλ“œλ₯Ό λŒ€μ‹  호좜


Proxy μ΄ˆκΈ°ν™”

μ—…λ‘œλ“œμ€‘..

  1. Proxy 객체 μΆ”κ°€
  2. μ‚¬μš©μžκ°€ Entity Method ν˜ΈμΆœν•˜λ©΄ Proxy 객체가 Persistence Context 에 μ΄ˆκΈ°ν™” μš”μ²­
  3. DB μ—μ„œ Persistence Context 1μ°¨ cache 둜 Entity 생성
  4. μš”μ²­ν•œ method λ₯Ό Proxy 객체가 λŒ€μ‹  μˆ˜ν–‰

Proxy 객체 νŠΉμ§•

1. Proxy κ°μ²΄λŠ” ν•œλ²ˆλ§Œ μ΄ˆκΈ°ν™” λœλ‹€.

Entity 의 Method 호좜 μ‹œ Proxy 객체에 μ‹€μ œ 객체 μ°Έμ‘°λ₯Ό λ³΄κ΄€ν•œλ‹€.

2. μ΄ˆκΈ°ν™” λ˜μ–΄λ„ νƒ€μž…μ€ κ·ΈλŒ€λ‘œ Proxy 객체 νƒ€μž…μ΄λ‹€.
μ΄ˆκΈ°ν™” 이후 μ‹€μ œ 엔티티에 μ ‘κ·Ό

            /**
             * μ˜μ†μ„± context 에 proxy 객체λ₯Ό λ¨Όμ € ν• λ‹Ή λ°›κ³  κ·Έ 후에
             * find λ©”μ†Œλ“œλ₯Ό 톡해 호좜 μ‹œ νƒ€μž… 비ꡐ
             * ( em.find μ‹œμ μ— μ‹€μ œ 객체가 μ‘°νšŒκ°€ λœλ‹€ )
             */
            Member refMember = em.getReference(Member.class, member.getId());
            System.out.println("Before refMember : "+refMember.getClass());

            /**
             *  DB 에 Entity 쑰회
             */
            refMember.getName();
            System.out.println("After refMember : "+refMember.getClass());

RESULT

Before refMember : class org.example.entity.Member$HibernateProxy$8oxssjRD
Hibernate: 
    select
        member0_.id as id1_0_0_,
        member0_.createDate as createDa2_0_0_,
        member0_.createUser as createUs3_0_0_,
        member0_.modifyDate as modifyDa4_0_0_,
        member0_.modifyUser as modifyUs5_0_0_,
        member0_.name as name6_0_0_,
        member0_.TEAM_ID as TEAM_ID7_0_0_,
        team1_.id as id1_1_1_,
        team1_.createDate as createDa2_1_1_,
        team1_.createUser as createUs3_1_1_,
        team1_.modifyDate as modifyDa4_1_1_,
        team1_.modifyUser as modifyUs5_1_1_,
        team1_.name as name6_1_1_ 
    from
        Member member0_ 
    left outer join
        Team team1_ 
            on member0_.TEAM_ID=team1_.id 
    where
        member0_.id=?
After refMember : class org.example.entity.Member$HibernateProxy$8oxssjRD

refMember둜 Proxy 객체λ₯Ό 생성후
refMember.getName(); λ₯Ό 톡해 Proxy 객체 μ΄ˆκΈ°ν™”λ₯Ό μ§„ν–‰ν–ˆμŒμ—λ„ λ™μΌν•˜κ²Œ PROXY 객체이닀

3. μ˜μ†μ„± Context μ‘°νšŒν•˜λŠ” 값이 μ‘΄μž¬ν•˜λ©΄
Proxy 객체λ₯Ό ν˜ΈμΆœν•΄λ„ Entity 객체 νƒ€μž…μ΄ λ°˜ν™˜λœλ‹€.

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

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

RESULT

Hibernate: 
    select
        member0_.id as id1_0_0_,
        member0_.createDate as createDa2_0_0_,
        member0_.createUser as createUs3_0_0_,
        member0_.modifyDate as modifyDa4_0_0_,
        member0_.modifyUser as modifyUs5_0_0_,
        member0_.name as name6_0_0_,
        member0_.TEAM_ID as TEAM_ID7_0_0_,
        team1_.id as id1_1_1_,
        team1_.createDate as createDa2_1_1_,
        team1_.createUser as createUs3_1_1_,
        team1_.modifyDate as modifyDa4_1_1_,
        team1_.modifyUser as modifyUs5_1_1_,
        team1_.name as name6_1_1_ 
    from
        Member member0_ 
    left outer join
        Team team1_ 
            on member0_.TEAM_ID=team1_.id 
    where
        member0_.id=?
m1 = class org.example.entity.Member
reference = class org.example.entity.Member

getReference λ₯Ό 톡해 Proxy 객체λ₯Ό ν˜ΈμΆœν–ˆμ§€λ§Œ Entity 객체 νƒ€μž…μ΄ λ°˜ν™˜ λ˜μ—ˆλ‹€.
m1 = class org.example.entity.Member
reference = class org.example.entity.Member

1. Proxy 객체가 μ°ΎλŠ” 객체가 Persistence Context ( 1μ°¨ Cache ) 에 이미 μ‘΄μž¬ν•˜λ©΄
Proxy 객체가 ν•΄λ‹Ή 객체 참쑰값을 κ°€μ§ˆ ν•„μš”κ°€μ—†λ‹€.
2. JPA λŠ” λ™μΌν•œ Transaction 에 λ™μΌν•œ 쑰건으둜 μ‘°νšŒλ˜λŠ” 값듀은 μ „λΆ€ λ™μΌν•΄μ•Όν•˜κΈ° λ•Œλ¬Έμ—
객체 νƒ€μž…μ„ λ°˜ν™˜

4. μ€€μ˜μ† μƒνƒœμΌλ•Œ Proxy μ΄ˆκΈ°ν™” μ‹œ μ˜ˆμ™Έ λ°œμƒ

            Member beforeDetach = em.getReference(Member.class, member.getId());
            System.out.println("reference : "+reference.getClass());
            em.detach(beforeDetach);
            beforeDetach.getName();

result

             *reference : class org.example.entity.Member$HibernateProxy$WC3xU0Il
             * org.hibernate.LazyInitializationException: could not initialize proxy [org.example.entity.Member#2] - no Session
             * 	at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:169)
             * 	at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:309)
             * 	at org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor.intercept(ByteBuddyInterceptor.java:45)
             * 	at org.hibernate.proxy.ProxyConfiguration$InterceptorDispatcher.intercept(ProxyConfiguration.java:95)
             * 	at org.example.entity.Member$HibernateProxy$WC3xU0Il.getName(Unknown Source)
             * 	at org.example.ProxyDetachPersistence.main(ProxyDetachPersistence.java:52)
             * 1μ›” 03, 2024 3:05:26 μ˜€ν›„ org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl stop
             * INFO: HHH10001008: Cleaning up connection pool [jdbc:h2:tcp://localhost/~/test;MODE=MySQL]

em.detach(beforeDetach); μ€€μ˜μ†ν™” 이후 beforeDetach.getName(); λ₯Ό 톡해
Proxy 객체λ₯Ό μ΄ˆκΈ°ν™” ν•˜λ©΄ LazyInitializationException μ˜ˆμ™Έκ°€ λ°œμƒν•œλ‹€.
μ΄λŠ” Proxy 객체의 μ΄ˆκΈ°ν™”κ°€ μ˜μ†μ„± Context λ₯Ό 톡해 μ΄λ£¨μ–΄μ§€λŠ”λ°
μ€€μ˜μ†ν™”λ‘œ μΈν•œ 객체 Session μ’…λ£Œ λ•Œλ¬Έμ΄λ‹€.

5. Proxy 탕비 μ²΄ν¬μ‹œ instance of μ‚¬μš© ꢌμž₯

            /**
             *:::::::::::::::::::::::::::::::
             * find ,reference !
             * :::::::::::::::::::::::::::::::
             */

            em.flush();
            em.clear();

            /**
             * find 둜 쑰회
             */
            Member mr1 = em.find(Member.class, member.getId());
            Member mr2 = em.getReference(Member.class, member1.getId());

            /**
             *  m1 , m2 νƒ€μž… 비ꡐ
             */
            System.out.println("m1 : "+mr1.getClass());
            System.out.println("m2 : "+mr2.getClass());
            System.out.println("m1 == m2 : "+(mr1.getClass() == mr2.getClass()));

            /**
             *:::::::::::::::::::::::::::::::
             * find ,reference Success !
             * :::::::::::::::::::::::::::::::
             */

            em.flush();
            em.clear();

            /**
             * find 둜 쑰회
             */
            Member mrs1 = em.find(Member.class, member.getId());
            Member mrs2 = em.getReference(Member.class, member1.getId());

            /**
             *  m1 , m2 νƒ€μž… 비ꡐ
             *  μ‹€μ œλ‘œλŠ” μ–΄λŠ 둜직으둜 μ˜¬μ§€ λͺ¨λ₯΄κΈ° λ•Œλ¬Έμ— νƒ€μž…λΉ„κ΅ν• λ•Œ
             *  == λ³΄λ‹€λŠ” instance of 둜 μ‚¬μš©ν•˜λŠ” 것이 μ’‹λ‹€.
             */
            System.out.println("mrs1 : "+mrs1.getClass());
            System.out.println("mrs2 : "+mrs2.getClass());
            System.out.println("mrs1  : "+(mrs1 instanceof  Member));
            System.out.println("mrs2  : "+(mrs2 instanceof  Member));

result

m1 : class org.example.entity.Member
m2 : class org.example.entity.Member$HibernateProxy$rOQSv1a1
m1 == m2 : false
Hibernate: 
    select
        member0_.id as id1_0_0_,
        member0_.createDate as createDa2_0_0_,
        member0_.createUser as createUs3_0_0_,
        member0_.modifyDate as modifyDa4_0_0_,
        member0_.modifyUser as modifyUs5_0_0_,
        member0_.name as name6_0_0_,
        member0_.TEAM_ID as TEAM_ID7_0_0_,
        team1_.id as id1_1_1_,
        team1_.createDate as createDa2_1_1_,
        team1_.createUser as createUs3_1_1_,
        team1_.modifyDate as modifyDa4_1_1_,
        team1_.modifyUser as modifyUs5_1_1_,
        team1_.name as name6_1_1_ 
    from
        Member member0_ 
    left outer join
        Team team1_ 
            on member0_.TEAM_ID=team1_.id 
    where
        member0_.id=?
mrs1 : class org.example.entity.Member
mrs2 : class org.example.entity.Member$HibernateProxy$rOQSv1a1
mrs1  : true
mrs2  : true

equal μ΄λ‚˜ ==λŠ” 객체의 λ‚΄μš©μ΄λ‚˜ μ°Έμ‘°κ°€ μ™„μ „νžˆ 동일해야 trueλ₯Ό λ°˜ν™˜ν•œλ‹€.
ν•˜μ§€λ§Œ μ‹€μ œ logic μ—μ„œ Proxy 와 μ‹€μ œ Entity 객체λ₯Ό κ΅¬λΆ„ν•˜μ§€ μ•Šκ³  μ‚¬μš©ν•˜κΈ° λ•Œλ¬Έμ— 객체 νƒ€μž…μ„ ν™•μΈν•˜λ €λ©΄ instance of λ₯Ό μ‚¬μš©ν•˜λŠ” 것이 μ’‹λ‹€.

0개의 λŒ“κΈ€