리포지터리와 모델 구현(JPA 중심)

철근콘크리트·2021년 1월 10일
0

DDD

목록 보기
4/4

이 장의 주제는 리포지터리 구현이다.

JPA를 이용한 리포지터리 구현

  • 애그리거트를 이떤 저장소에 저장하느냐에 따라 리포지터리를 구현하는 방법이 다르기 때문에 모든 구현 기술에 대해 알 수는 없다.

  • 도메인 모델과 리포지터리를 구현할 때 선호하는 기술을 꼽자면 JPA를 들 수 있다.

  • ORM 표준인 JPA를 이용해서 리포지터리와 애그리거트를 구현하는 방법에 대해 살펴보자.


리포지터리 기본 기능 구현.

  • 아이디로 애그리거트 조회하기
  • 애그리거트 저장하기
public interface OrderRepository{
	public Order findById(OrderNo no);
    	public void save(Order order);
}

: 주문 애그리거트는 Order 루트 엔티티를 비롯패 OrderLine, Orderer, ShippingInfo 등 다양한 객체를 포함하는데, 이 구성 요소 중에서 Order 루트 엔티티를 기준으로 리포지터리 인터페이스를 작성한다.

"findById()는 아이디에 해당하는 애그리거트가 존재하면 Order를 리턴하고, 존재하지 않으면 null을 리턴한다."

import org.springframework.stereotype.Repository;
import shop.order.domain.Order;
import shop.order.domain.OrderNo;
import shop.order.domain.OrderRepository;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

@Repository
public class JpaOrderRepository implements OrderRepository{
	@PersistenceContext
    private EntityManager entityManager; 
    
    @Override
    public Order findById(OrderNo id){
    	return entityManager.find(Order.class, id);
    }
    
    @Override
    public void save(Order order){
    	entityManager.persist(order);
    }
    
}

애그리거트를 수정한 결과를 저장소에 반영하는 메서드를 추가할 필요는 없다.
JPA를 사용하면 트랜잭션 범위에서 변경한 데이터를 자동으로 반영하기 때문이다.


매핑 구현

엔티티와 벨류 기본 매핑 구현

  • 애그리거트 루트는 엔티티이므로 @Entity로 매핑 설정한다.
  • 한 테이블에 엔티티와 밸류 데이터가 같이 있다면,
    ( 밸류는 @Embeddable로 매핑 설정/ 밸류 타입 프로퍼티는 @Embedded 매핑 설정한다. )

Order 애그리거트 루트 엔티티는 @Embedded를 이용해서 밸류 타입 프로퍼티를 설정한다.

@Entity
public class Order{
	@Embedded
    	private Orderer orderer;
    
   	 @Embedded
   	 private ShippingInfo shippingInfo;

}

JPA의 @Entity와 @Embeddable로 클래스를 매핑하려면 기본 생성자를 제공해야 한다.

  • 하이버네이트와 같은 JPA 프로바이더는 DB에 데이터를 읽어와 매핑된 객체를 생성할 때 기본 생성자를 사용해서 객체를 생성한다.
@Embeddable
public class Receiver{
	@Column(name = "reveiver_name")
    	private String name;
      	@Column(name = "receiver_phone")
        private String phone;
    

	protected Receiver(){} // JPA를 적용하기 위해 기본 생성자 추가.
    
    public Receiver(String name, String phone){
    	this.name = name;
        this.phone = phone; 
    
    }


}

: 기본 생성자는 JPA 프로바이더가 객체를 생성할 때만 사용한다. 기본 생성자를 다른 코드에서 사용하면 값이 온전하지 못한 객체를 만들게 된다. 이런 이유로 다른 코드에서 기본 생성자를 사용하지 못하도록 protected를 선언한다.

Hibernate는 클래스를 상속한 프록시 객체를 이용해서 지연 로딩을 구현한다. 이 경우 프록시 클래스에서 상위 클래스의 기본 생성자를 호출할 수 있어야 하므로 지연 로딩 대상이 되는 @Entity와 @Embeddable의 기본 생성자는 private이 아닌 protected로 지정해야 한다.

0개의 댓글