Published on

[ JPA ] 연관관계 매핑시 알아야 할 영속성 전이 기능(cascade)

Authors
  • avatar
    Name
    유사공대생
    Twitter

프록시

엔티티를 조회할 때, 연관된 엔티티들이 모두 사용되지는 않는다. 예를 들어 회원 엔티티를 조회할 때 연관된 팀 엔티티는 비즈니스 로직에 따라 사용될 때도 있지만 그렇지 않을 때도 있다.

  • 회원 엔티티
@Entity
public class Member{
    private String username;

    @ManyToOne
    private Team team;

    public Team getTeam(){
        return team;
    }

    public String getUsername() {
        return username;
    }
}
  • 팀 엔티티
@Entity
public class Team{
    private String name;

    public String getName() {
        return name;
    }
}
  • 회원과 팀 정보를 출력하는 비즈니스 로직
public void printUserAndTeam(String memberId){
    Member member = em.find(Member.class, memberId);
    Team team = member.getTeam();
    System.out.print("회원이름: "+ member.getUsername());
    System.out.print("회원이름: "+ member.getUsername());
}
  • 회원정보만 출력하는 비즈니스 로직
public String printUser(String memberId){
    Member member = em.find(Member.class, memberId);
    System.out.println("회원 이름: "+ member.getUsername());
}

printUserAndTeam() 메소드는 memberId로 회원 엔티티를 찾아서 회원은 물론이고 회웡과 연관된 팀의 이름도 출력한다.

반면에 printUser() 메소드는 회원 엔티티만 사용하므로 em.find()로 회원 엔티티를 조회할 때 회원과 연관된 팀 엔티티(Member.team)까지 데이터베이스에서 함께 조회해두는 것은 효율적이지 않다.

JPA는 이런 문제를 해결하기 위해 엔티티가 실제 사용될 때 까지 데이터베이스 조회를 지연하는 방법을 제공하는데 이것을 지연 로딩이라고 한다. 다시 말해서, team.getName()처럼 팀 엔티티의 값을 실제 사용하는 시점에 데이터베이스에서 팀 엔티티에 필요한 데이터를 조회한다.

이 방법을 사용하면 printUser() 메소드는 회원 데이터만 데이터베이스에서 조회해도 된다.

그런데 지연 로딩 기능을 사용하기 위해서는 실제 엔티티 객체 대신에 데이터베이스 조회를 지연할 수 있는 가짜 객체가 필요한데 이것을 프록시 객체라고 한다.

프록시 기초

JPA에서 식별자로 엔티티 하나를 조회할 때는 EntityManager.find()를 사용한다. 이 메소드는 영속성 컨텍스트에 엔티티가 없으면 데이터베이스를 조회한다.

Member member = em.find(Member.class, "member1");

이렇게 엔티티를 직접 조회하면 엔티티를 실제 사용하든 사용하지 않든 데이터베이스를 조회하게 된다. 엔티티를 실제 사용하는 시점까지 데이터베이스 조회를 미루고 싶다면 EntityManager.getReference() 메소드를 사용하면 된다.

Member member = em.getReference(Member.class, "member1");

이 메소드를 호출할 때 JPA는 데이터베이스를 조회하지 않고 실제 엔티티 객체도 생성하지 않는다. 대신에 데이터베이스 접근을 위임한 프록시 객체를 반환한다.

image