JAVA/프로젝트

리팩토링: DB접근 줄여 실행 속도 향상 시키기

whyHbr 2024. 6. 29. 20:35
728x90
반응형
@Transactional(readOnly = true)
public ProductDetailResponse getProductDetail(
    Long accommodationId, Long productId,
    LocalDate checkInDate, LocalDate checkOutDate,
    int personNumber) {
    validateInputs(checkInDate, checkOutDate, personNumber);

    Accommodation accommodationEntity = accommodationRepository.findById(accommodationId)
        .orElseThrow(() -> new AccommodationException(ErrorType.NOT_FOUND));

    Product productEntity = productRepository.findById(productId)
        .orElseThrow(() -> new ProductException(ErrorType.NOT_FOUND));

    if (personNumber > productEntity.getMaximumNumber()) {
        throw new ProductException(ErrorType.INVALID_NUMBER_OF_PEOPLE);
    }

    List<ProductInfoPerNight> availableProductPerNights = productInfoPerNightRepository
        .findByProductIdAndDateRange(productId, checkInDate, checkOutDate);

    for (LocalDate date = checkInDate; date.isBefore(checkOutDate); date = date.plusDays(1)) {
        if (!productInfoPerNightRepository.existsByProductIdAndDate(productId, date)) {
            throw new ProductException(ErrorType.NOT_FOUND);
        }
    }

    ProductInfoPerNight availableProductPerNight = productInfoPerNightRepository
        .findByProductIdAndDateRange(productId, checkInDate, checkOutDate).get(0);

    int night = (int) ChronoUnit.DAYS.between(checkInDate, checkOutDate);
    int totalPrice = night * availableProductPerNight.getPrice();

    ProductImageResponse productImageResponse = ProductImageResponse.from(
        productEntity.getProductImage());
    ProductOptionResponse productOptionResponse = ProductOptionResponse.from(
        productEntity.getProductOption());

    return ProductDetailResponse.from(productEntity, accommodationEntity.getName(),
        availableProductPerNight.getPrice(), totalPrice, night, productImageResponse,
        productOptionResponse);

기존 로직

 

새로운 로직

@Transactional(readOnly = true)
public ProductDetailResponse getProductDetail(
    Long accommodationId, Long productId,
    LocalDate checkInDate, LocalDate checkOutDate,
    int personNumber) {
    validateInputs(checkInDate, checkOutDate, personNumber);

    Accommodation accommodationEntity = accommodationRepository.findById(accommodationId)
        .orElseThrow(() -> new AccommodationException(ErrorType.NOT_FOUND));

    Product productEntity = productRepository.findById(productId)
        .orElseThrow(() -> new ProductException(ErrorType.NOT_FOUND));

    if (personNumber > productEntity.getMaximumNumber()) {
        throw new ProductException(ErrorType.INVALID_NUMBER_OF_PEOPLE);
    }

    List<ProductInfoPerNight> availableProductPerNights = productInfoPerNightRepository
        .findByProductIdAndDateRange(productId, checkInDate, checkOutDate);

    // 날짜 범위 내의 모든 날짜가 존재하는지 확인하고 메모리서 처리
    long expectedNights = ChronoUnit.DAYS.between(checkInDate, checkOutDate);
    if (availableProductPerNights.size() < expectedNights) {
        throw new ProductException(ErrorType.NOT_FOUND);
    }

    // 총 가격 계산
    int totalPrice = availableProductPerNights.stream()
        .mapToInt(ProductInfoPerNight::getPrice)
        .sum();

    ProductImageResponse productImageResponse = ProductImageResponse.from(
        productEntity.getProductImage());
    ProductOptionResponse productOptionResponse = ProductOptionResponse.from(
        productEntity.getProductOption());

    return ProductDetailResponse.from(productEntity, accommodationEntity.getName(),
        availableProductPerNights.get(0).getPrice(), totalPrice, (int) expectedNights,
        productImageResponse, productOptionResponse);

 

728x90