본문 바로가기
스프링

Id로 연관관계 짓기(엔티티로 연관관계x)

by 순원이 2024. 4. 9.
@Data
@Entity
@NoArgsConstructor
public class Member {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;
    
  	public Member(Long id) {
      this.id = id;
  	}
    
  	public Member(String name) {
      this.name = name;
  	}
}
@Data
@Entity
@NoArgsConstructor
public class Team {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;


    @ManyToOne
    @JoinColumn(name = "member_id")
    private Member member;
	 
  	public Team(Member member) {
        this.member = member;
    }
}

객체를 활용한 JPA 연관관계 사용

@Service
@RequiredArgsConstructor
public class TeamService {

    private final TeamRepository teamRepository;
    private final MemberRepository memberRepository;

    @Transactional
    public void save(Long memberId) throws NotFoundException {
        Member member = memberRepository.findById(memberId).orElseThrow(NotFoundException::new);
        Team team = new Team(member);
        teamRepository.save(team);
    }
}

위의 코드는 Spring을 처음하는 사람에게 가장 익숙할 수 있는 JPA 연관관계를 사용하는 코드이다.

위의 코드를 사용하며 아래와 같은 sql 쿼리가 생성된다.

Hibernate: 
    select
        member0_.id as id1_0_0_,
        member0_.name as name2_0_0_ 
    from
        member member0_ 
    where
        member0_.id=?
Hibernate: 
    insert 
    into
        team
        (member_id) 
    values
        (?, ?)

내가 하고 싶은 건 Team을 저장하는 것인데 member 조회 쿼리까지 나가는 겁니다. 

불필요한 쿼리를 없애고자 

연관관계를 엔티티가 아닌 Id로 하고자 합니다.

@Data
@Entity
@NoArgsConstructor
public class Team {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    private Long memberId;
	 
  	public Team(Long memberId) {
        this.memberId = memberId;
    }
}
@Service
@RequiredArgsConstructor
public class TeamService {

    private final TeamRepository teamRepository;
    private final MemberRepository memberRepository;

    @Transactional
    public void save(Long memberId) {
        Team team = new Team(memberId);
        teamRepository.save(team);
    }
}
Hibernate: 
    insert 
    into
        team
        (member_id) 
    values
        (?, ?)

이렇게 된다면 저희에게 필요한 team 저장하는 쿼리만 나가게 됩니다.

 

단점           

  • 데이터 무결성이 보장이 안된다.
    • DDD 같은 경우는 루트엔티티가 내부의 객체들을 관리하기 때문에 무결성이 보장이 된다.
    • 그러나 DDD가 아닌 경우 데이터 무결성이 보장이 안된다
    • 또한 관리가 복잡할 수도 있다
      • 예를 들면 member가 삭제되면 team도 삭제되어야 한다. 엔티티로 연관관계를 지을 경우 자동으로 삭제된다. 그러나 Id로 연관관계를 할 경우 직접 삭제한 memberId를 가지고 있는 team을 찾아 삭제해야 한다.

 

엔티티 연관관계와 id로 연관관계 중 어떤 게 실무에 적합해 보이나요?