상품 관리

심규환·2022년 2월 8일
0

Shop

목록 보기
3/10

상품관리는 QueryDsl에 조건문을 줘서 원하는 값을 조회하는 방법을 쓰도록 하겠습니다. 조건은 상품 등록일, 상품 판매 상태, 상품명, 상품 등록자, 가격을 추가로 작성할 수 있습니다.
기본적으로 상품관리 페이지는 등록한 모든 상품을 보여주며 조건을 통해서 필터를 걸어서 조회하도록 하겠습니다.

DTO

ItemSearchDto.Java

public class ItemSearchDto {

    // all : 상품 등록 전체
    // 1d : 최근 하루 동안 등록된 상품
    // 1w : 최근 일주일 동안 등록된 상품
    // 1m : 최근 한 달 동안 등록된 상품
    // 6m : 최근 6개월 동안 등록된 상품
    private String searchDateType;

    private ItemSellStatus searchSellStatus;

    // itemNm : 상품명
    // createBy : 상품 등록자 ID
    private String searchBy;

    private String searchQuery = "";
    
    private Long price;
}

Repository

ItemRepositoryCustom.Java

Spring Data JPA와 같이 연동시키기 위해 Custom 인터페이스와 구현체를 만들어 보겠습니다. 꼭 구현체는 Impl을 붙여줘야 합니다. 자세한 내용은 아래의 링크에 확인 가능합니다.
https://docs.spring.io/spring-data/jpa/docs/2.1.3.RELEASE/reference/html/#repositories.custom-implementations

public interface ItemRepositoryCustom {
    Page<Item> getAdminItemPage(ItemSearchDto itemSearchDto, Pageable pageable);
}

ItemRepositoryCustomImpl.Java

Querydsl에서는 BooleanExpression을 사용해서 간단하면서도 재사용성 가능하도록 동적쿼리를 만들 수 있게 해줍니다.
BooleanExpression의 값이 null이라면 조건문에 무시되기 때문에 해당 조건에 만족하지 않으면 null로 반환시키도록 합니다.

  • JPA를 사용해야 하기 때문에 JPAQueryFactory를 생성자 의존성 주입을 통해 넣어줍니다. 어노테이션을 사용해도 좋습니다.
  • 원하는 조건에 맞는 메서드를 QueryDsl의 where문에 맞게 생성합니다.(반환값 : BooleanExpression)
  • queryFactory의 where에 원하는 조건들을 다 넣어줍니다.
  • 조회문으로 사용할 getAdminItemPage를 반환값 Page로 하여 메서드를 만들어줍니다. 반환값으로는 PageImpl 구현체를 사용했고 매개변수는 List형태인 content, pageable, size(total) 입니다.
public class ItemRepositoryCustomImpl implements ItemRepositoryCustom{

    private JPAQueryFactory queryFactory;

    public ItemRepositoryCustomImpl(EntityManager em){
        this.queryFactory = new JPAQueryFactory(em);
    }

    private BooleanExpression searchSellStatusEq(ItemSellStatus searchSellStatus){
        return searchSellStatus == null ? null : QItem.item.itemSellStatus.eq(searchSellStatus);
    }

    private BooleanExpression regDtsAfter(String searchDateType){

        LocalDateTime dateTime = LocalDateTime.now();

        if(StringUtils.equals("all", searchDateType) || searchDateType == null){
            return null;
        } else if(StringUtils.equals("1d", searchDateType)){
            dateTime = dateTime.minusDays(1);
        } else if(StringUtils.equals("1w", searchDateType)){
            dateTime = dateTime.minusWeeks(1);
        } else if(StringUtils.equals("1m", searchDateType)){
            dateTime = dateTime.minusMonths(1);
        } else if(StringUtils.equals("6m", searchDateType)){
            dateTime = dateTime.minusMonths(6);
        }

        return QItem.item.regTime.after(dateTime);
    }

    private BooleanExpression searchByLike(String searchBy, String searchQuery){
        if(StringUtils.equals("itemNm", searchBy)){
            return QItem.item.itemNm.like("%" + searchQuery + "%");
        } else if(StringUtils.equals("createdBy", searchBy)){
            return QItem.item.createdBy.like("%" + searchQuery + "%");
        }
        return null;
    }
    
    private BooleanExpression underPrice(Long price){
        if( price <= 0){
            return null;
        }
        return QItem.item.price.loe(price);
    }
    
    private BooleanExpression itemNmLike(String searchQuery){
        return StringUtils.isEmpty(searchQuery) ? null : QItem.item.itemNm.like("%" + searchQuery + "%");
    }
    
    @Override
    public Page<Item> getAdminItemPage(ItemSearchDto itemSearchDto, Pageable pageable) {
        List<Item> results = queryFactory
                .selectFrom(QItem.item)
                .where(regDtsAfter(itemSearchDto.getSearchDateType()),
                        searchSellStatusEq(itemSearchDto.getSearchSellStatus()),
                        searchByLike(itemSearchDto.getSearchBy(),
                                itemSearchDto.getSearchQuery()),
                                underPrice(itemSearchDto.getPrice())
                .orderBy(QItem.item.id.desc())
                .offset(pageable.getOffset())
                .limit(pageable.getPageSize())
                .fetch();

        long total = results.size();

        return new PageImpl<>(results, pageable, total);
    }

    

ItemRepository.Java

만들어 놓은 ItemRepositoryCustom을 상속받게 합니다.

public interface ItemRepository extends JpaRepository<Item, Long>, QuerydslPredicateExecutor<Item>, ItemRepositoryCustom {

Controller

ItemController.Java

상품관리 페이지("/admin/items")에서 페이지를 누르면 "/admin/items/{page}"로 전달되어 페이징 처리된 값을 받게 됩니다.
먼저 page 값이 안들어 있을 수 있기 때문에 Optional로 감싸준 뒤, 유효성 검사 후 PageRequest.of 를 사용하여 Pageable을 생성합니다. (PageRequest는 Pageable의 구현체)
한 페이지에 5개로 제한했습니다.

@GetMapping(value = {"/admin/items", "/admin/items/{page}"})
public String itemManage(ItemSearchDto itemSearchDto, @PathVariable("page")Optional<Integer> page, Model model){
    Pageable pageable = PageRequest.of(page.isPresent() ? page.get() : 0, 5);
    Page<Item> items = itemService.getAdminItemPage(itemSearchDto, pageable);
    model.addAttribute("items", items);
    model.addAttribute("itemSearchDto", itemSearchDto);
    model.addAttribute("maxPage", 5);
    return "item/itemMng";
}

Service

ItemService.Java

성능 최적화를 위하여 Transactional을 readOnly로 설정합니다. Service는 전달받은 메시지를 그대로 Repository로 전달해줍니다.

@Transactional(readOnly = true)
public Page<Item> getAdminItemPage(ItemSearchDto itemSearchDto, Pageable pageable){
   return itemRepository.getAdminItemPage(itemSearchDto, pageable);
}
profile
장생농씬가?

0개의 댓글