본문 바로가기
Back-End/JPA

[Spring Data JPA] 도메인 엔티티 클래스 정의

by 달의 조각 2022. 8. 28.

DDD(Domain Driven Design)란 도메인 위주의 설계 기법을 말한다.

  • 애그리거트(Aggregate): 도메인 영역을 상위 수준과 하위 수준으로 나눌 수 있다. 비슷한 업무들을 하나로 묶은 그룹을 말한다.
  • 애그리거트 루트(Aggregate Root): 각 애그리거트를 대표하는 도메인으로, 루트(부모 테이블)의 기본키 정보를 다른 도메인(자식 테이블)들이 외래키 형태로 가지고 있다.
  • 애그리거트 간의 관계
    • 1 : N
    • N : N → 1 : N, N : 1 관계로 재설계한다.

 


'

도메인 엔티티 클래스 정의

 

DB 테이블 간에 관계는 외래키를 통해 맺어지지만, 클래스끼리의 관계는 객체의 참조로 맺어진다.

  • 테이블: 외래키를 통해 다른 테이블의 데이터를 조회한다. (조인)
  • 클래스: 객체 참조로 다른 클래스의 데이터를 조회한다. (컬렉션: List, Set)

 

애그리거트 객체 매핑 규칙

Spring Data JDBC 사용을 위해서 도메인 엔티티 클래스의 관계를 DDD의 애그리거트 매핑 규칙에 맞게 변경해야 한다.

  1. 모든 엔티티 객체의 상태는 애그리거트 루트를 통해서만 변경할 수 있다.
    • 도메인 규칙을 적용하여 일관성을 유지할 수 있다.
  2. 하나의 동일한 애그리거트 내에서는 엔티티 간에 객체로 참조한다.
  3. 애그리거트 루트 간의 참조는 객체 참조 대신에 ID로 참조한다.
    • 1 : 1 / 1 : N 관계일 때
      • 테이블 간의 외래키 방식과 동일 (AggregateReference 사용)
    • N : N  관계일 때
      1. 외래키 방식인 ID 참조와 객체 참조 방식이 함께 사용된다.
      2. 참조할 테이블에 해당하는 클래스의 @Id 필드를 멤버 변수로 가지는 별도의 참조 클래스를 사용한다.
      3. 1 : N, N : 1 관계로 변경한다.
      4. 중간에서 참조해 주는 클래스를 통해 다시 1 : N : 1 관계로 변경한다.

 


 

엔티티 구현

 

Member - Order 루트 매핑

1 : N 관계의 애그리거트 루트: AggregateReference 클래스(애그리거트 간의 참조를 나타냄)로 감싸 준다.

 

@Getter
@Setter
@Table("ORDERS")
public class Order {

    @Id
    private long orderId;
    
    // 테이블의 외래키처럼 memberId를 추가해서 참조한다.
    private AggregateReference<Member, Long> memberId;
}

 

Order - Coffee 루트 매핑

N : N 관계의 애그리거트 루트: 1 : N, N : 1 관계로 풀어 줄 엔티티(CoffeeRef)가 필요하다.
@Getter
@Setter
@Table("ORDERS")
public class Order {

    // Order : CoffeeRef = 1:N
    @MappedCollection(idColumn = "ORDER_ID")
    private Set<CoffeeRef> orderCoffees = new LinkedHashSet<>();
    ...
}
  • 동일한 애그리거트 내에서는 객체 참조를 한다. (Order와 CoffeeRef)
  • @MappedCollection(idColumn = "Order_ID")
    • 엔티티 클래스 간 연관 관계를 맺어 주는 정보
    • idColumn은 외래키(테이블 간 관계를 맺어 주는 주체)에 해당되는 컬럼이다.
@Getter
@AllArgsConstructor
@Table("ORDER_COFFEE")
public class CoffeeRef {
    private long coffeeId;
    private int quantity;
}
  • 주문 애그리거트 ⊃ CoffeeRef, 커피 애그리거트 ⊃ Coffee이지만, N : N 관계이므로 AggregateReference로 coffeeId를 감싸지 않아도 된다.

댓글