엔티티를 조회할 때 연관관계를 맺고있는 다른 엔티티도 같이 조회된다. 하지만 항상 연관된 엔티티 정보가 필요한 것은 아니므로 불필요한 데이터베이스 조회가 생기는 것이다. Employee 정보를 얻기위해 아래와 같이 조회한다면 내부적으로 Department 정보까지 동시에 조회를 한다.
publicclassRealSubject{ publicrequest(){...} } publicclassProxySubjectextendsRealSubject{ private RealSubject realSubject = null; public String request(){ // 실제 데이터가 필요한 시점에 객체 초기화 및 데이터를 불러온다. if(realSubject == null) { // 초기화 및 참조 보관 // JPA의 경우 DB 조회 realSubject = new RealSubject(); } return realSubject.request(); } } publicclassClient{ publicvoidselectName(){ RealSubject proxy = new ProxySubject(); proxy.request(); ..... } }
프록시 객체를 얻고 초기화하는 작업은 영속성 컨텍스트를 통해서 한다. 즉, 프록시 객체는 영속성 컨텍스트에서 관리되고 있는 객체이다. 준영속(detached) 상태의 프록시 객체를 사용하려고 하면 예외가 발생된다.
엔티티매니져의 getReference() 메소드를 통해서 프록시 객체를 얻을 수 있다.
getReference()로 프록시 객체를 얻으려고 할때 이미 영속성 컨텍스트에 실제 객체가 있는경우 프록시 객체가 아닌 실제 객체를 리턴한다. 반면, 프록시 객체를 조회 했다면 find()로 조회 하더라도 실제 객체가 아닌 프록시 객체가 리턴된다. 이는 영속성 컨텍스트가 항상 엔티티의 동일성(identity)을 보장하기 위함이다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
// 실제 객체가 먼저 조회되어 영속성 컨텍스트에 존재하는 경우 Employee realEmployee = em.find(Employee.class, "id1"); Employee proxyEmployee = em.getReference(Employee.class, "id1"); // realEmployee, proxyEmployee 모두 실제 엔티티 이다. Assert.assertTrue(realEmployee == proxyEmployee); // 성공
// 프록시 객체를 조회한 뒤 실제 객체를 조회하려고 하는 경우 Employee proxyEmployee = em.getReference(Employee.class, "id1"); Employee realEmployee = em.find(Employee.class, "id1"); // realEmployee, proxyEmployee 모두 프록시 객체이다. Assert.assertTrue(realEmployee == proxyEmployee); // 성공
// 타입 비교 Assert.assertFalse(proxyEmployee.getClass() == Employee.class); Assert.assertTrue(proxyEmployee instanceof Employee);
프록시 객체를 사용시 동등성(equal) 비교시 주의 해야한다. IDE를 통해 자동으로 equals() 오버라이딩 메소드를 생성한 경우 제대로 동작하지 않는다. 내부적으로 같은 타입인지 비교하기 위해 getClass()를 사용하고,(프록시 객체는 실제 객체를 상속받음) 필드 값들을 비교하기 위해서 getter 메소드가 아닌 필드에 직접 접근하여 값을 얻는다.(프록시 객체가 초기화 되지 않았 을 수 있음) 타입비교는 instanceof를 사용하고, 필드 값은 getter 메소드를 통해 얻어야 한다.
NOTE JPA에서 즉시 로딩을 할때 내부조인(INNER JOIN)이 아니라 외부조인(LEFT OUTTER JOIN)을 사용한다. 이는 null값이 허용되는 경우 데이터가 누락되는 것은 막을 수 있지만, 성능상 안좋을 수 있다. INNER JOIN을 사용해야 되는 경우에는 아래와 같이 설정해 주면된다. (둘중 한가지 방법 선택) @JoinColumn(name=”DEPARTMENT_ID”, nullable=false) @ManyToOne(fetch= FetchType.EAGER, optional=false)
Department dept = em.find(Department.class, "id01"); dept.getEmployees().remove(0); // 연관관계 삭제 // DELETE FROM EMPLOYEE WHERE EMPLOYEE_ID = ? 실행 됨 dept.getEmployees().clear(); // 연관된 모든 Employee 삭제됨
Posts
(책리뷰) 쿠버네티스 완벽 가이드
AWS EKS 를 사용하여 쿠버네티스 환경에서 운영을 하고 있는데, 좀 더 제대로 이해하고 싶은 마음이 들어 쿠버네티스 완벽 가이드를 보게 되었다. 새로운 기술을 접할 때 공식 문서를 보는 것 보다 책을 통해서 공부 하는 것을 좋아한다.대부분의 경우 문서화가 잘되어 있
지난 10년. 어떤 기술 흐름속에 살았을까?
8/16. 입사한지 딱 10년이 되었다. 대학생 때 프로그래밍 이라는 것을 접하기 시작한 이후 지금까지 지난 14년이 넘는 기간동안 어떤 기술의 변화 속에서 지내왔는지 정리 해 보려고 한다.각 기술은 개인적으로 접하기 시작한 시점으로 실제 유행했던 시기와 조금 다를 수
2020년 회고
2019년 2018년 2017년 코로나.언제 부터 시작된 건지 이제 기억이 나지 않지만, 지난 일년은 코로나로 인해 많은 것들이 달라졌다. 일단, 7살 딸내미가 유치원에 가지 못했다. 계속 되는 휴원에, 잠깐이라도 등원 할 수 있는 유치원이나 어린이집 등 보육시설을 찾
언젠가 또 힘들어 하고 있을지 모르는 나에게
무언 가에 몰입 하는 것은 많은 정신적 고통을 안겨준다.나는 개발자로서 많은 부분에 몰입을 한다.frontend, backend, modeling, architecture, ci/cd, infra.. 등등..가끔 다른 역할자의 영역을 침범하는 우를 범하기도 한다. 이번
React 개발 환경 구성 (react, webstorm)
개발 tool은 webstorm 을 사용하고, react는 create-react-app 을 통해 생성하도록 하겠습니다. npm 5 버전 이상 설치되어 있어야 합니다. Create React App eslint 설정 상대경로 지옥 피하기. jsconfig.json 설정