반응형

연관 관계 편의 메소드를 사용하기 전에

이 부분을 이해하시려면 우선 영속성 컨텍스트(Persistence Context)에 대한 이해가 필요합니다. 관련 글은 다른 블로그에 자세히 설명된 게 있어서 링크로 첨부하니 확인해보세요!

 

JPA / 영속성 컨텍스트 / 1차 캐시 / 쓰기 지연

"T아카데미 / JPA 프로그래밍 기본기 다지기 - 김영한 " 강좌를 듣고 정리한 글입니다. 영속성 컨텍스트를 영속성 컨텍스로 관리하면 어떤 이점을 갖을까 1. 1차 캐시 / 엔티티 동일성 보장 2. 쓰기

www.ecsimsw.com

 

연관 관계 편의 메소드

JPA에서 양방향 연관 관계를 설정했을 때 연관 관계의 주인의 반대쪽 필드는 mappedby를 설정하여 읽기 전용으로 쓰게 됩니다. 그런데 일대다 중 다 쪽에만 연관 관계를 설정하면 객체 지향적이지 않을뿐더러 DB에서 데이터를 조회하기 전까지는 일대다 중 다 쪽에만 값이 세팅되어 일 쪽 Entity에서는 연관 관계를 모르기 때문에 일 쪽의 값을 출력해보면 데이터가 나오지 않습니다.

 

예제 코드

아래 코드는 teamA를 생성하고 memberA에 teamA를 넣어 연관 관계를 설정하는 코드입니다. 이 코드는 문제가 없어보일 수 있지만 실행하면 마지막 줄은 출력되지 않습니다.

 

memberA에는 teamA가 들어갔지만 반대인 teamA는 memberA와의 연관 관계가 설정되지 않았기 때문에 teamA에는 member와 관련된 아무런 값도 설정되지 않았기 때문입니다.

 

따라서 teamA가 memberA를 알려면 em.flush() 후 em.clear()를 통해 영속성 컨텍스트를 깨끗하게 비워 DB에서 값을 찾을 수 있도록 해주면 되는데 이보다 객체 지향적이면서, 1차 캐시의 영속성 컨텍스트와 실제 DB 데이터와의 데이터 차이 문제를 해결하기 위해 일대다 양쪽에 데이터를 넣어주는 게 필수적입니다. 아래 예제를 통해 확인해봅시다!

 

* 반드시 영속성 컨텍스트에 대한 내용을 숙지하고 보세요!

 

Team teamA = new Team();
team.setName("teamA");
em.persist(teamA);

Member memberA = new Member();
memberA.setName("memberA");

// memberA에 연관 관계 설정
memberA.setTeam(teamA);
em.persist(memberA);

System.out.println("memberA.getTeam : " + memberA.getTeam());
System.out.println("teamA.getMembers() : " + teamA.getMembers(0));

 

teamA에도 연관 관계 설정

teamA.getMember().add(memberA); 한 줄만 추가해주면 됩니다.

 

Team teamA = new Team();
team.setName("teamA");
em.persist(teamA);

Member memberA = new Member();
memberA.setName("memberA");

// memberA에 연관 관계 설정
memberA.setTeam(teamA);
em.persist(memberA);

// teamA에 연관 관계 설정
teamA.getMembers().add(memberA);

System.out.println("memberA.getTeam : " + memberA.getTeam());
System.out.println("teamA.getMembers() : " + teamA.getMembers(0));

 

Member Entity에 연관 관계 편의 메소드 생성

위 방법으로 해결할 수 있지만 같은 코드 반복을 방지하기 위해 Member Entity에서 연관 관계 편의 메소드를 생성합니다. 이렇게 연관 관계 편의 메소드를 사용하면 코드 중복을 방지하고 양방향 연관 관계 매핑에서 한쪽에만 연관 관계가 설정되는 것을 방지할 수 있습니다.

 

@Entity
@Getter
public Member {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "MEMBER_ID")
    private Long id;
    private String name;
    private Team team;
    
    public changeTeam(Team team) {
        
        // Member에 이미 Team이 설정되어 있을 경우
        if(this.team != null) {
         
            // team에서 해당 Entity를 제거
            this.team.getMembers().remove(this);
        }
        
        // 해당 member Entity에 파라미터로 들어온 team 연관 관계 설정
        this.team = team;
        
        // 파라미터로 들어온 team Entity에 member 연관 관계 설정
        team.getMembers().add(this);
    }
}
반응형

+ Recent posts