JPA 스터디를 진행하며 Proxy에 대한 강의를 보며 내용을 정리하고 있다보니 옛날 생각이 많이 났다.
이런 얘기를 하면 또또 틀딱거릴거 같은데 눈물없이 들을 수 없는 얘기일 것이다.아마도
이부분은 중요하지 않으니 Proxy에 대해서 먼저 설명해보자.
하이버네이트가 내부적으로 실제 클래스를 상속 받아 만드는 가짜 클래스
변수나 메서드 이름 등이 똑같지만 값은 가지고 있지 않은 껍데기만 있는 객체
실제 클래스가 생성되었을 때 매핑되기 위해 참조값을 가지고 있다.
프록시를 사용하려면 기존에 객체를 find 메서드로 찾았다면 getReference 메서드로 찾으면 된다.
em.find() : db 통해서 실제 엔티티 객체 조회
em.getReference() : db 조회가 아닌 가짜, 프록시 엔티티 객체를 조회
프록시는 애초에 실제하는 값이 아니므로 db 조회를 할 필요가 없으니 로그를 보면 조회 쿼리도 발생하지 않는다.

public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
try {
Member member1 = new Member();
member1.setName("adsgsda");
em.persist(member1);
em.flush();;
em.clear();
Member findMember = em.getReference(Member.class, member1.getId());
System.out.println("findid = " + findMember.getId());
System.out.println("findNm = " + findMember.getName());
tx.commit();
} catch (Exception e) {
tx.rollback();
}
finally {
em.close();
}
emf.close();
}

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "MEMBER_ID")
private Long id;
System.out.println("findid = " + findMember.getId());
System.out.println("findNm = " + findMember.getName());
- PK값인 id를 JPA가 할당하여 생성하므로, 하이버네이트가 해당 long값을 알고 있다
스터디원이 링크를 보내와 정확하게 다시 확인해주셨다.
내용이 깊으니 정리를 대충 하자면
프록시 초기화 과정을 담당하는 ByteBuddyInterceptor 라는 클래스가 있음
정확하게는 이 놈의 상위 추상 클래스 AbstractLazyInitializer 가 담당함@Override public final Serializable getIdentifier() { if (isUninitialized() && isInitializeProxyWhenAccessingIdentifier() ) { initialize(); } return id; }해당 조건문에서 보통 false 되므로 id가 리턴되는 것임
저 조건은 hibernate.jpa.compliance.proxy 옵션이 기본값이 false 라서
그런데 명심해야할 것은 자바 빈 규약에 맞는 호출을 해야지만 해당 구문을 탄다는 것!
get+필드명이 아니면 안된다와 다른 조건이 있었는데, 더이상 알 필요는 지금 없을 것 같다..
중요한 것은 ID값을 알고 있으므로 DB에 조회할 이유가 없다는 것!
즉 findMember.getId()까지는 초기화요청을 하지 않는다!
private static void logic(Member m1, Member m2) {
System.out.println("m1 == m2 : " + (m1 instanceof Member));
System.out.println("m2 == m1 : " + (m2 instanceof Member));
}
JPA는 영속성 컨텍스트의 동일성을 보장해야 한다.
키값이 같은 동일한 객체가 두개가 존재하면 안되므로
그래서 코드를 트랜잭션과 영속성 컨택스트는 시작과 끝을 맞춰서 짜는게 일반적이라고 한다.
PersistenceUnitUtil.isLoaded(Object entity)
//정확하게는 팩토리에서 써야함
emf.getPersistenceUnitUtil().isLoaded(entity)
이렇게 프록시에 대해서 알아보았다.
프록시 서버와는 또 비슷비슷하면서 다른게 역시 어려운게 참 많은거 같다.
강의를 쭉 듣다보니 이거 delegate네 라는 생각이 그냥 들었다.
그리고 자료에서도 delegate라는 단어가 나와버리면서 추억에 젖어들고 말았던 것.
근본은 잊지 말자는 생각에 리마인드의 개념으로 작성해보고자 한다.
왜 눈물이 나냐면 C#은 스레드와 같이 동적처리를 시작하는 변수이기 때문에
여기서부터 사람들이 멘탈이 터지고 힘들어하기 때문이다.
정말 아무것도 모를시절 회사에서 혼나면서 동적처리를 어떻게 배웠을지 상상해보라..
- 메서드를 간접 참조
- 런타임에 동적 기능
public delegate [반환형식] [이름] (매개변수)
namespace ConsoleApplication
{
delegate int FuncDelegate(int a, int b);
class Program
{
static int Plus(int a, int b)
{
return a + b;
}
static int Minus(int a, int b)
{
return a - b;
}
static void Main(string[] args)
{
FuncDelegate plusDelegate = Plus;
FuncDelegate minusDelegate = Minus;
Console.WriteLine(plusDelegate(5, 10));
Console.WriteLine(minusDelegate(20, 10));
}
}
}
출력)
15
10
왜 쓰는지 정확하게 모를 수 있다. 조금 더 길게 한번 보자.
using System;
namespace ConsoleApp1
{
delegate void FuncDelegate(string str);
class Program
{
static void Func1(string str)
{
Console.WriteLine("Helo1 : " + str);
}
static void Func2(string str)
{
Console.WriteLine("Helo2 : " + str);
}
static void Func3(string str)
{
Console.WriteLine("Helo3 : " + str);
}
static void Func4(string str)
{
Console.WriteLine("Helo4 : " + str);
}
static void Main(string[] args)
{
FuncDelegate plusDelegate = null;
plusDelegate += Func1;
plusDelegate += Func2;
plusDelegate += Func3;
plusDelegate += Func4;
plusDelegate("Text");
}
}
}
출력 )
Hello1 : Text
Hello2 : Text
Hello3 : Text
Hello4 : Text
이른바 C의 함수 포인터와도 비슷한 애들이라 이말인 것이다.
왜 델리게이트가 중요하냐면, C#에서는 이놈을 이해해야만 이벤트라는 거대한 산을 만날 수 있다.
이벤트 핸들러가 델리게이트이고, 심지어 스레드의 시작을 알리는 TheadStart라는 함수도 델리게이트 였다.
아닌가?
무튼 동적처리 하는 놈들은 다 위험한 친구들이니 이제부터 더 난이도가 높아질거 같다.
출처 : https://m.blog.naver.com/dontcryme/30093395886
https://huiyu.tistory.com/entry/C-%EA%B8%B0%EC%B4%88-%EC%9D%B4%EB%B2%A4%ED%8A%B8%EC%99%80-%EB%8D%B8%EB%A6%AC%EA%B2%8C%EC%9D%B4%ED%8A%B8-Event-Delegate
https://www.csharpstudy.com/CSharp/CSharp-delegate-concept.aspx