그렇다고 굵직한것만 보고 넘어갈 수는 없어.
이 딜레마를 어떻게 해야함????
그냥 예방접종 맞는다는 느낌으로 세세한걸 봐야하나?
볼때는 진심이다.
마치 영원히 기억할것처럼...
예를들자면
em.find 로 엔티티를 가져온다음에
em.createQuery("select * from ~~~"); 를 적용하면 어떻게 될거같아??
일단 여기서 첫번째로 드는 의문은
두번째 쿼리는 1차캐시로부터 데이터를 가져오느냐 그렇지 않느냐 임.
두번쨰 쿼리는 데이터를 1차캐쉬로부터 가져오지 않아.
2차캐쉬가 있더라도 데이터를 2차캐쉬로부터도 가져오지 않아.
쿼리를 명시하면 데이터는 db로부터 가져와.
그러면 두번쨰로 드는 의문이 생겨.
db데이터가 다르면??
첫번째 find는 2차캐시 및 영속성컨텍스트에서 데이터를 가져왔고
두번째 쿼리는 db에서 가져왔으니 둘은 다른건가?? 둘을 다르게 저장할 수 있는가??
팩트는 이러함. 두번쨰 쿼리가 db에서 가져와서 데이터 값이 다르지?? 그러면 두번째 값을 fetch는 하되
그것을 파기하고 영속성컨텍스트의 값으로 대체함.
즉, 두개의 find는 같은 엔티티를 가리킴. 동일성 동등성 전부 보장되는 상태로.
기억했지?
자 그러면 이제 실제 복잡한 상황을 디버깅 할 때에는 저런 자그마한 공리들을 모아서 해결해야돼.
자 여기서는 ~~이러이러 하니까 이렇게 작동하고, 그 작동을 바탕으로 ~~가 일어났으니까 저건 이렇게 되고~~ 이렇게.
근데, 그 공리들 기억날까???
다음에 다시 또 문제해결해야될 떄가 있으면
또다시
em.find 하고 나서
db데이터가 변경된 이후
em.createQuery("select ~~") 하면 어떻게 되지???
이걸 또 다시 테스트해봐야할거라고....
근데 그렇다고 테스트를 안해볼 수는 없잖아??
저 문제의 예시상황은 또 2차캐쉬를 집어넣어서 생각해 볼 만 한데, 그러면 2차캐쉬가 존재하는 상태로 em.find로 2차캐쉬로부터 데이터를 받은 후, em.createQuery("select ~")를 하면 쿼리 선택되는것과 쿼리 선택 이후 2차캐쉬 상태는 어떻게 될까?
이게 두번째 쿼리의 CacheStoreMode 에 따라서 달라지는건데... 그게 안먹혀..
나같은경우엔 세세한거는 경험으로 남기면 다시하면 생각나고, 말한대로 굵직한건 어느정도 암기레벨로 되게끔, 혹은 암기가 안되도 시작점 한두군데만 찾아보면 흐름이 후두두 나올정도로는 익힘
난 블로그에 남길 생각이야.... 기록을 해둬야겠어.... ㅠㅠ
기록비용이 너무 쎄지만 않다면, 그냥 자기만족용으로라도 기록이 좀 필요한거같아. 세세한것들이 다시 생각나면 좋을텐데 나는 기억이 안나더라
실험코드를 무진장 많이 짜게 돼
아 당연히 그런 기록을 해두는게 낫지. 구글링으로 맨앞 한두페이지에서 바로나오는거면 상관없지만, 그거 이상의 작업이 필요하면 아카이브 떠놔야하더라고
나 실험코드 진짜 무진장 많이 남기면서 배우는 스타일인데... 문서를 어떻게 정리하는게 좋을까?
공부하고 있는 책의 진도에 맞춰서 장을 쓰고, 거기에서 파생된 코드들을 대충 제목설명달아서 남겨볼까? 그러면 기록비용은 적은데 다시 읽어보기는 좀 헬일거같아
em.reference 랑 em.find 차이 머게 ㅇㅅㅇ 이제 JPA 좀 공부한 것 같아서 질문해봄
존나 쉽잖아. 프록시로 가져오느냐 엔티티를 가져오느냐
reference로 가져오면 LAZY로 늦게 가져오니까 상황 따라서 성능 이점을 챙길 수 있다는 말이었는데 뭐 ㅇㅅㅇ
어떻게 활용할지에 대해서는 아직 생각 못해봤어. getReference는 쿼리가 안나가니까 좋은거같음.
그치 OSIV를 기본적으로 닫을꺼니까
근데 엔티티들을 인자로 받아들이는 메소드들 전부 프록시임을 가정하고 해야하는거 맞지??예를들면public void printName(Member member) {sout(member.name);}하면 안되고public void printName(Member member) {
sout(member.getName()); } 해야하니까
이게 살짝 헷갈리는게 필드 네임이 name 이라고 했을때 this.name 을 써도 되느냐 아니면 프록시니까 this.getName()을 써야하느냐 이었는데 프록시의 작동방식상 this의 경우에는 그냥 필드를 그대로 가져다 써도 된다고 생각함
프록시의 작동방식은 약간 aop랑도 영역이 겹치는 측면이 있는데, this.method() 를 하는 경우랑 this.field 를 호출하는 경우랑 좀 헷갈리는거같아. Transactional 같은거 걸때 관련 문제들 많이 발생했음. 아마 aop쓸때도 문제 발생할듯
이게 엔티티를 인자로 받는 메소드들을 위해서 getter를 무조건 열어놔야하고 또 코드가 get때문에 엄청 더러워지는거 맞지?
엔티티가 프록시일수도 있어서. 근데 이 문제 좀 당연한거같기도 한게, 그래서인지 필드는 프라이빗으로 놓는거같더라. 필드 쓰지 마라고
엔티티의 필드를 닫는건 엔티티 자체보다는 객체지향적으로 하면 안된다고 접근해야할 것 같은데
필드 직접 사용하면 객체지향원칙에 어긋나?
DTO 사용 이유 검색해서 찾아봐 ㅇㅅㅇ