본문 바로가기
Books/도메인 주도 개발 시작하기

Chapter5. 스프링 데이터 JPA를 이용한 조회 기능

by YoonJong 2024. 4. 8.
728x90

  • CQRS : 명령 모델과 조회 모델을 분리하는 패턴
    • 명령 모델 : 상태를 변경하는 기능 구현 ex) 회원 가입, 주문 취소
    • 조회 모델 : 데이터를 보여주는 기능 ex) 주문 목록, 주문 상세, 회원 상태
  • 스프링 데이터 JPA 간단 예제
// Entity 클래스 생성
@Entity
@Getter
public class Book {

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

    private String title;
    private String author;
}

// Repository 인터페이스 생성
public interface BookRepository extends JpaRepository<Book, Long> {
}

// Service 클래스 생성
@Service
public class BookService {

    private final BookRepository bookRepository;

    @Autowired
    public BookService(BookRepository bookRepository) {
        this.bookRepository = bookRepository;
    }

    public List<Book> findAllBooks() {
        return bookRepository.findAll();
    }

    public Optional<Book> findBookById(Long id) {
        return bookRepository.findById(id);
    }

    public Book saveBook(Book book) {
        return bookRepository.save(book);
    }

    public void deleteBook(Long id) {
        bookRepository.deleteById(id);
    }
}

BookRepository 인터페이스에서 다양한 메서드를 작성할 수 있다.

public interface BookRepository extends JpaRepository<Book, Long> {
	
	List<Book> findByAuthor(String author);
	
	// JPQL
	@Query("SELECT b FROM Book b WHERE b.title LIKE %:keyword%")
	List<Book> findByTitleContaining(@Param("keyword") String keyword);
	
	// Native Query
	@Query(value = "SELECT * FROM books WHERE author = :author", nativeQuery = true)
	List<Book> findByAuthorWithNativeQuery(@Param("author") String author);

 // 페이징(Paging) 처리
 // 제목에 특정 단어가 포함된 책을 검색하고 페이징 처리
  @Query("SELECT b FROM Book b WHERE b.title LIKE %:keyword%")
  Page<Book> findByTitleContaining(@Param("keyword") String keyword, Pageable pageable);
}

// Controller ( 페이징 처리 사용 )
@GetMapping("/books")
public Page<Book> getBooksByTitleContaining(
        @RequestParam String keyword,
        @RequestParam(defaultValue = "0") int page, // 0 (첫번째 페이지)
        @RequestParam(defaultValue = "10") int size) { // 10개 가져온다.
    return bookRepository.findByTitleContaining(keyword, PageRequest.of(page, size));
}
  • 동적쿼리 → Queydsl 을 사용하자!
public PageImpl<CouponMasterAdminResDto> findAllCouponMasterByDateOrCouponName(
        Pageable pageable,  String searchStartDate, String searchEndDate, String selectSearchCondition, String searchCondition,
        String selectStatus, String searchMainCategory) {

        LocalDateTime startDateTime = DateTimeUtils.parseStartDateTime(searchStartDate);
        LocalDateTime endDateTime = DateTimeUtils.parseEndDateTime(searchEndDate);

        List<CouponMasterAdminResDto> list = queryFactory
            .select(new QCouponMasterAdminResDto(
                // 필요한 객체
            ))
            .from(couponMaster)
            .where(
                couponMaster.createdAt.between(startDateTime, endDateTime),
                searchContainsCouponName(selectSearchCondition, searchCondition), // 동적쿼리
                searchIsUsableOrIsExposed(selectStatus),
                searchFilterByMainCategory(searchMainCategory)
            )
            .orderBy(couponMaster.createdAt.desc())
            .offset(pageable.getOffset())
            .limit(pageable.getPageSize())
            .fetch();

private BooleanExpression searchContainsCouponName(String selectSearchCondition, String searchCondition) {
        switch (selectSearchCondition) {
            case "couponName":
                return couponMaster.couponName.contains(searchCondition);
            case "couponMasterUuid":
                return couponMaster.masterId.eq(searchCondition);
            case "createUser":
                return couponMaster.createdUser.contains(searchCondition);
            case "modifiedUser":
                return couponMaster.modifiedUser.contains(searchCondition);
        }
        return couponMaster.couponName.contains(searchCondition)
                .or(couponMaster.masterId.eq(searchCondition))
                .or(couponMaster.createdUser.contains(searchCondition))
                .or(couponMaster.modifiedUser.contains(searchCondition));
    }
728x90

댓글