์๋ฐ ORM ํ์ค JPA ํ๋ก๊ทธ๋๋ฐ : ๊ต๋ณด๋ฌธ๊ณ
์๋ฐ ORM ํ์ค JPA ํ๋ก๊ทธ๋๋ฐ - ๊ธฐ๋ณธํธ : ์ธํ๋ฐ
์ค์ Entity ๋์ DB ์กฐํ๋ฅผ ์ง์ฐํ ์ ์๋ ๊ฐ์ฒด๋ฅผ ๋งํ๋ค.
proxy ๊ฐ์ฒด๋ ์ค์ Entity ๋ฅผ ์์
๋ฐ์์ ๋ง๋ค์ด์ง ๊ฐ์ฒด์ด๋ค.
์ฌ์ฉ์ ์
์ฅ์์ Entity ์ธ์ง Proxy ๊ฐ์ฒด์ธ์ง ๊ตฌ๋ถํ์ง ๋ชปํ๋ค.
Proxy ๊ฐ์ฒด๋ ์ค์ ๊ฐ์ฒด ์ฐธ์กฐ๋ฅผ ๋ณด๊ดํ๋๋ฐ ์ฒ์ Proxy ๊ฐ์ฒด๊ฐ ์์ฑ๋๋ฉด null
์ด ํ ๋น๋๋ค.
์ฌ์ฉ์๋ฅผ ๋์ ํ์ฌ Entity ์ Method ํธ์ถํ๋ค.
SUMMARY
1. proxy ๊ฐ์ฒด๋์ค์ Entity ๋ฅผ ์์
๋ฐ์์ ๋ง๋ค์ด์ง ๊ฐ์ฒด
2. ์ค์ ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ์ฌ ๋ณด๊ดํ๋ฉฐ ์ฒ์ ์์ฑ์null
ํ ๋น
3. Entity ์ method ๊ฐ ํธ์ถ๋๋ฉด Proxy ๊ฐ์ฒด์ ์ค์ ๊ฐ์ฒด์ ์ฐธ์กฐ๋ฅผ ๋ณด๊ด
4. ์ฌ์ฉ์๋ฅผ ๋์ ํ์ฌ ์ค์ ๊ฐ์ฒด์ ๋ฉ์๋๋ฅผ ๋์ ํธ์ถ
- Proxy ๊ฐ์ฒด ์ถ๊ฐ
- ์ฌ์ฉ์๊ฐ Entity Method ํธ์ถํ๋ฉด Proxy ๊ฐ์ฒด๊ฐ Persistence Context ์ ์ด๊ธฐํ ์์ฒญ
- DB ์์ Persistence Context 1์ฐจ cache ๋ก Entity ์์ฑ
- ์์ฒญํ method ๋ฅผ Proxy ๊ฐ์ฒด๊ฐ ๋์ ์ํ
Entity ์ Method ํธ์ถ ์ 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());
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 ๊ฐ์ฒด์ด๋ค
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());
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 ์ ๋์ผํ ์กฐ๊ฑด์ผ๋ก ์กฐํ๋๋ ๊ฐ๋ค์ ์ ๋ถ ๋์ผ
ํด์ผํ๊ธฐ ๋๋ฌธ์
๊ฐ์ฒด ํ์ ์ ๋ฐํ
Member beforeDetach = em.getReference(Member.class, member.getId());
System.out.println("reference : "+reference.getClass());
em.detach(beforeDetach);
beforeDetach.getName();
*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 ์ข ๋ฃ
๋๋ฌธ์ด๋ค.
/**
*:::::::::::::::::::::::::::::::
* 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));
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
๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ์ข๋ค.