Updated:

1. 개요

JPA는 가짜 객체라고하는 프록시를 제공하며, 프록시를 통해 편리한 기능을 제공한다. 이번에는 프록시 (Proxy)에 대해 알아보도록 하자.

2. 프록시 (Proxy)

프록시는 실제 클래스를 상속 받아서 만들기때문에 사용하는 입장에서 진짜 객체인지 프록시 객체인지 구분 없이 사용할 수 있다. 사용자가 프록시 객체를 호출하면, 프록시 객체가 실제 객체의 메서드를 호출한다. EntityManager의 getReference()를 통해 프록시를 호출할 수 있다.

3. 초기화

프록시 객체는 실제로 처음으로 사용하는 시점에 초기화 된다. 초기화 시 DB를 조회하여 영속성 컨텍스트에 저장하고, 프록시 객체에서 실제 엔티티 호출 시 영속성 컨텍스트의 값을 반환한다.

4. 특징

  • 프록시 객체는 처음 사용할 때 한 번만 초기화되고, 프록시 객체를 통해 실제 엔티티에 접근 가능

  • 영속성 컨텍스트에 이미 해당 엔티티가 존재한다면, em.getReference()를 호출해도 실제 엔티티 반환

  • 영속성 컨텍스트의 도움을 받을 수 없는 준영속 상태일 때, 프록시를 초기화하면 예외 발생

5. 예제

5-1. 예제 코드

[Member.java]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@Entity
public class Member {

    @Id @GeneratedValue
    @Column(name = "MEMBER_ID")
    private Long id;

    @Column(name = "USERNAME")
    private String username;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }
}

[JpaMain.java]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class JpaMain {

    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
        EntityManager em = emf.createEntityManager();

        EntityTransaction tx = em.getTransaction();
        tx.begin();

        try {
            Member member = new Member();
            member.setUsername("hello");

            em.persist(member);

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

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

            tx.commit();
        } catch (Exception e) {
            tx.rollback();
            e.printStackTrace();
        } finally {
            em.close();
        }

        emf.close();
    }
}

Line 11 ~ 17 : Member 저장 후 영속성 컨텍스트 초기화

Line 19 : 프록시 호출

Line 20 : 프록시 객체 출력

Line 21 : Line 19에서 ID를 통해 프록시를 호출하여 ID를 알고 있는 상태이므로 실제 객체 없어도 해당 값 반환

Line 22 : 프록시에서 실제 객체를 호출하여 값을 얻어옴. 이 때 select 쿼리 호출

5-2. 실행 결과

출처 : 자바 ORM 표준 JPA 프로그래밍 - 기본편

Updated:

Leave a comment