Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cart / purchase JPA n+1 문제 해결 #141

Merged
merged 10 commits into from
Feb 1, 2024
2 changes: 1 addition & 1 deletion src/main/java/com/sportsecho/common/aop/TimeTraceAop.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public void memberProduct() {
public void purchase() {
}

@Around("user()")
@Around("user() || memberProduct() || purchase()")
public Object execute(ProceedingJoinPoint joinPoint) throws Throwable {
long start = System.currentTimeMillis();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.NamedAttributeNode;
import jakarta.persistence.NamedEntityGraph;
import jakarta.persistence.NamedSubgraph;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
Expand All @@ -19,6 +22,13 @@
@Builder
@NoArgsConstructor
@AllArgsConstructor
@NamedEntityGraph(
name = "graph.MemberProduct",
attributeNodes = {
@NamedAttributeNode(value = "product", subgraph = "productGraph")
}, subgraphs = {
@NamedSubgraph(name = "productGraph", attributeNodes = @NamedAttributeNode("productImageList"))
})
public class MemberProduct {

@Id
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,20 @@
import com.sportsecho.memberProduct.entity.MemberProduct;
import java.util.List;
import java.util.Optional;
import org.springframework.data.jpa.repository.EntityGraph;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

public interface MemberProductRepository extends JpaRepository<MemberProduct, Long> {

Optional<MemberProduct> findByProductIdAndMemberId(Long productId, Long memberId);

@EntityGraph(value = "graph.MemberProduct", type = EntityGraph.EntityGraphType.FETCH)
List<MemberProduct> findByMemberId(Long memberId);

List<MemberProduct> findByMemberId(Long id);

void deleteAllByMemberId(Long memberId);
@Modifying
@Query("DELETE FROM MemberProduct mp WHERE mp.member.id = :memberId")
void deleteByMemberId(@Param("memberId") Long memberId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ public void deleteCart(Long cartId, Member member) {
@Override
@Transactional
public void deleteAllCart(Member member) {
memberProductRepository.deleteAllByMemberId(member.getId());
memberProductRepository.deleteByMemberId(member.getId());
}

private Product findProduct(Long productId) {
Expand Down
11 changes: 11 additions & 0 deletions src/main/java/com/sportsecho/purchase/entity/Purchase.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.NamedAttributeNode;
import jakarta.persistence.NamedEntityGraph;
import jakarta.persistence.NamedSubgraph;
import jakarta.persistence.OneToMany;
import java.util.ArrayList;
import java.util.List;
Expand All @@ -25,6 +28,14 @@
@Builder
@AllArgsConstructor
@NoArgsConstructor
@NamedEntityGraph(name = "graph.Purchase",
attributeNodes = {
@NamedAttributeNode(value = "purchaseProductList", subgraph = "purchaseProductListGraph")
},
subgraphs = {
@NamedSubgraph(name = "purchaseProductListGraph", attributeNodes = {
@NamedAttributeNode(value = "product")})
})
public class Purchase extends TimeStamp {

@Id
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
package com.sportsecho.purchase.repository;

import com.sportsecho.purchase.entity.Purchase;
import io.lettuce.core.dynamic.annotation.Param;
import java.util.List;
import java.util.Optional;
import org.springframework.data.jpa.repository.EntityGraph;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

public interface PurchaseRepository extends JpaRepository<Purchase, Long> {

@EntityGraph(value = "graph.Purchase", type = EntityGraph.EntityGraphType.FETCH)
@Query("SELECT p FROM Purchase p WHERE p.member.id = :memberId ORDER BY p.createdAt DESC")
List<Purchase> findByMemberId(@Param("memberId") Long memberId);

@EntityGraph(value = "graph.Purchase", type = EntityGraph.EntityGraphType.FETCH)
@Query("SELECT p FROM Purchase p WHERE p.id = :purchaseId")
Optional<Purchase> findByIdWithProducts(Long purchaseId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public PurchaseResponseDto purchase(PurchaseRequestDto requestDto, Member member
}

// 재고 확인 후 차감
updateStock(memberProductList);
decreaseStock(memberProductList);

// 구매 인스턴스 생성
Purchase purchase = PurchaseMapper.INSTANCE.fromPurchaseRequestDto(requestDto, member);
Expand All @@ -59,7 +59,7 @@ public PurchaseResponseDto purchase(PurchaseRequestDto requestDto, Member member
purchaseRepository.save(purchase);

// 장바구니 비우기
memberProductRepository.deleteAllByMemberId(member.getId());
memberProductRepository.deleteByMemberId(member.getId());

return PurchaseMapper.INSTANCE.toResponseDto(purchase);
}
Expand All @@ -82,11 +82,11 @@ public List<PurchaseResponseDto> getPurchaseList(Member member) {
@Transactional
public void cancelPurchase(Long purchaseId, Member member) {

Purchase purchase = purchaseRepository.findById(purchaseId).orElseThrow(
() -> new GlobalException(PurchaseErrorCode.NOT_FOUND_PURCHASE)
Purchase purchase = purchaseRepository.findByIdWithProducts(purchaseId).orElseThrow(() ->
new GlobalException(PurchaseErrorCode.NOT_FOUND_PURCHASE)
);
checkMember(purchase, member);
updateStock(purchase);
increaseStock(purchase);

purchaseProductRepository.deleteByPurchaseId(purchaseId);
purchaseRepository.deleteById(purchaseId);
Expand Down Expand Up @@ -117,17 +117,7 @@ private List<PurchaseProduct> createPList(List<MemberProduct> memberProductList,
return pList;
}

private void updateStock(Purchase purchase) {
List<PurchaseProduct> purchaseProductList = purchase.getPurchaseProductList();

for (PurchaseProduct purchaseProduct : purchaseProductList) {
Product product = purchaseProduct.getProduct();
product.increaseQuantity(purchaseProduct.getProductsQuantity());
productRepository.save(product);
}
}

private void updateStock(List<MemberProduct> memberProductList) {
private void decreaseStock(List<MemberProduct> memberProductList) {

for (MemberProduct memberProduct : memberProductList) {
Product product = memberProduct.getProduct();
Expand All @@ -136,11 +126,19 @@ private void updateStock(List<MemberProduct> memberProductList) {
throw new GlobalException(PurchaseErrorCode.OUT_OF_STOCK);
} else {
product.decreaseQuantity(memberProduct.getProductsQuantity());
productRepository.save(product);
}
}
}

private void increaseStock(Purchase purchase) {
List<PurchaseProduct> purchaseProductList = purchase.getPurchaseProductList();

for (PurchaseProduct purchaseProduct : purchaseProductList) {
Product product = purchaseProduct.getProduct();
product.increaseQuantity(purchaseProduct.getProductsQuantity());
}
}

private void checkMember(Purchase purchase, Member member) {
if (!purchase.getMember().getId().equals(member.getId())) {
throw new GlobalException(PurchaseErrorCode.ACCESS_DENIED);
Expand Down
Loading