Java 기반 애플리케이션에서의 코드 레벨에서 사용하는 데이터를 데이터베이스에 저장, 업데이트, 조회할 수 있도록 해주는 표준 API
Spring에서 사용할 수 있는 데이터 엑세스 기술 중 하나로 SQL 중심 기술이다.
JPA처럼 ORM(Object Relational Mapping) 기술을 사용하지만 JPA의 기술적 복합도를 낮춘 기술이다. 애플리케이션의 규모가 상대적으로 크지 않고, 복잡하지 않을 경우에 Spring Data JDBC가 뛰어난 생산성을 보여줄거라 기대하고 있다고 한다. 그리고 Spring Data Jpa와 달리 단방향 연관관계만 지원한다. 그리고 미리 작성된 DDL이 존재하여야 한다.
dependencies {
...
...
implementation 'org.springframework.boot:spring-boot-starter-data-jdbc'
}
@Repository
public interface UserRepository extens CrudRepository<User, Long> {
...
}
CrudRepository 인터페이스를 상속받아 Repository를 구현한다.
DDD는 도메인 주도 설계로 도메인 위주의 설계 기법을 의미한다. 여기서 도메인이란 비즈니스적인 어떤 업무 영역과 관련이 있다.
예를 들어 주문 앱을 만든다면 주문과 관련된 기능에는 고객이 음식을 주문하는 과정, 주문하는 음식을 처리하는 과정, 조리된 음식을 배달하는 과정 등의 도메인 지식들을 서비스 계층에서 비즈니스 로직으로 구현해야 한다.
업무 도메인의 묶음을 말한다.
배달앱의 경우 업무 도메인을 나눈다면 회원, 주문, 음식, 배달, 결제로 크게 나눌 수 있다. 이 각각의 요소들을 애그리거트라고 한다.
애그리거트를 좀 더 세부적으로 나눈다면 그 중 대표하는 도메인을 애그리거트 루트라고 한다.
- 애그리거트 루트 선정 기준
다른 도메인들과의 관계에서 연관이 주가 되는 도메인을 애그리거트 루트로 선정한다.
데이터베이스의 테이블 간 관계로 본다면, 애그리거트 루트는 부모 테이블이 되고 애그리거트 루트가 아닌 다른 도메인들은 자식 테이블이 된다.
애그리거트 루트의 기본키 정보들은 다른 도메인들의 외래키 형태로 가지게 된다.
1. 모든 엔티티 객체의 상태는 애그리거트 루트를 통해서만 변경할 수 있다.
2. 동일한 하나의 애그리거트 내에서는 엔티티 간에 객체로 참조한다.
3. 애그리거트 루트 간의 참조는 객체 참조 대신에 ID로 참조한다.
- 1대1과 1대N 관계일 때는 테이블 간의 외래키 방식과 동일
- N대N 관계일 때는 외래키 방식인 ID 참조와 객체 참조 방식이 함께 사용
-> 애그리거트 루트를 통해서 나머지 엔티티에 접근한다는 것은 어떤식으로든 애그리거트 루트가 나머지 모든 엔티티에 대한 객체를 직간접적으로 참조 할 수 있다는 의미
@Getter
@Setter
@NoArgsConstructor
public class Member {
@Id
private long memberId;
...
}
@Getter
@Setter
@NoArgsConstructor
@Table(name = "ORDERS")
public class Order {
@Id
private long orderId;
private AggregateReference<Member, Long> memberId;
...
}
외래키가 존재해야 하는 곳에 AggregateReference
를 넣어주고 참조할 객체와 아이디의 타입을 설정해준다.
다대다의 관계는 1:N:1로 분할한다.
@Getter
@Setter
@Table("ORDERS")
public class Order {
@Id
private long orderId;
private AggregateReference<Member, Long> memberId;
@MappedCollection(idColumn = "ORDER_ID")
private Set<CoffeeRef> orderCoffees = new LinkedHashSet<>();
...
...
}
@Getter
@AllArgsConstructor
@Table("ORDER_FOOD")
public class FoodRef {
private long foodId;
private int quantity;
}
주문 정보와 음식 주문 정보와의 연관 관계 매핑은 @MappedCollection(idColumn = "ORDER_ID")
을 이용한다. 이는 애그리거트 루트와 애그리거트 간의 연관관계를 나타낼때 사용한다.
public interface MemberRepository extends CrudRepository<Member, Long> {
Optional<Member> findByEmail(String email);
}
Spring Data JDBC에서는 CrudRepository
라는 인터페이스를 제공하고 있다. 인터페이스내에 정의한 메서드 findByEmail()
을 쿼리 메서드라고 부른다. 해당 쿼리 메서드는 다음과 같이 내부적으로 쿼리문으로 변환된다.
SELECT * FROM MEMBER WHERE MEMBER.EMAIL = ?
또한 @Query
어노테이션을 사용해서 직접 쿼리문을 작성할 수 있다.
public interface MemberRepository extends CrudRepository<Member, Long> {
Optional<Member> findByEmail(String email);
@Query("SELECT * FROM MEMBER WHERE EMAIL = :email")
Optional<Member> findByMember(String email);
}