diff --git a/src/main/java/com/sportsecho/common/aop/TimeTraceAop.java b/src/main/java/com/sportsecho/common/aop/TimeTraceAop.java index e02a5656..f12a7f56 100644 --- a/src/main/java/com/sportsecho/common/aop/TimeTraceAop.java +++ b/src/main/java/com/sportsecho/common/aop/TimeTraceAop.java @@ -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(); diff --git a/src/main/java/com/sportsecho/memberProduct/entity/MemberProduct.java b/src/main/java/com/sportsecho/memberProduct/entity/MemberProduct.java index 945262f8..381f8e90 100644 --- a/src/main/java/com/sportsecho/memberProduct/entity/MemberProduct.java +++ b/src/main/java/com/sportsecho/memberProduct/entity/MemberProduct.java @@ -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; @@ -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 diff --git a/src/main/java/com/sportsecho/memberProduct/repository/MemberProductRepository.java b/src/main/java/com/sportsecho/memberProduct/repository/MemberProductRepository.java index 64535d1c..82ef8491 100644 --- a/src/main/java/com/sportsecho/memberProduct/repository/MemberProductRepository.java +++ b/src/main/java/com/sportsecho/memberProduct/repository/MemberProductRepository.java @@ -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 { Optional findByProductIdAndMemberId(Long productId, Long memberId); + @EntityGraph(value = "graph.MemberProduct", type = EntityGraph.EntityGraphType.FETCH) + List findByMemberId(Long memberId); - List findByMemberId(Long id); - - void deleteAllByMemberId(Long memberId); + @Modifying + @Query("DELETE FROM MemberProduct mp WHERE mp.member.id = :memberId") + void deleteByMemberId(@Param("memberId") Long memberId); } diff --git a/src/main/java/com/sportsecho/memberProduct/service/MemberProductServiceImplV1.java b/src/main/java/com/sportsecho/memberProduct/service/MemberProductServiceImplV1.java index 755682a0..93f83901 100644 --- a/src/main/java/com/sportsecho/memberProduct/service/MemberProductServiceImplV1.java +++ b/src/main/java/com/sportsecho/memberProduct/service/MemberProductServiceImplV1.java @@ -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) { diff --git a/src/main/java/com/sportsecho/purchase/entity/Purchase.java b/src/main/java/com/sportsecho/purchase/entity/Purchase.java index 889ab319..71324a32 100644 --- a/src/main/java/com/sportsecho/purchase/entity/Purchase.java +++ b/src/main/java/com/sportsecho/purchase/entity/Purchase.java @@ -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; @@ -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 diff --git a/src/main/java/com/sportsecho/purchase/repository/PurchaseRepository.java b/src/main/java/com/sportsecho/purchase/repository/PurchaseRepository.java index c0e86806..bd9eac74 100644 --- a/src/main/java/com/sportsecho/purchase/repository/PurchaseRepository.java +++ b/src/main/java/com/sportsecho/purchase/repository/PurchaseRepository.java @@ -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 { + @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 findByMemberId(@Param("memberId") Long memberId); + + @EntityGraph(value = "graph.Purchase", type = EntityGraph.EntityGraphType.FETCH) + @Query("SELECT p FROM Purchase p WHERE p.id = :purchaseId") + Optional findByIdWithProducts(Long purchaseId); } diff --git a/src/main/java/com/sportsecho/purchase/service/PurchaseServiceImplV1.java b/src/main/java/com/sportsecho/purchase/service/PurchaseServiceImplV1.java index 020c733c..e5db2b6c 100644 --- a/src/main/java/com/sportsecho/purchase/service/PurchaseServiceImplV1.java +++ b/src/main/java/com/sportsecho/purchase/service/PurchaseServiceImplV1.java @@ -44,7 +44,7 @@ public PurchaseResponseDto purchase(PurchaseRequestDto requestDto, Member member } // 재고 확인 후 차감 - updateStock(memberProductList); + decreaseStock(memberProductList); // 구매 인스턴스 생성 Purchase purchase = PurchaseMapper.INSTANCE.fromPurchaseRequestDto(requestDto, member); @@ -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); } @@ -82,11 +82,11 @@ public List 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); @@ -117,17 +117,7 @@ private List createPList(List memberProductList, return pList; } - private void updateStock(Purchase purchase) { - List purchaseProductList = purchase.getPurchaseProductList(); - - for (PurchaseProduct purchaseProduct : purchaseProductList) { - Product product = purchaseProduct.getProduct(); - product.increaseQuantity(purchaseProduct.getProductsQuantity()); - productRepository.save(product); - } - } - - private void updateStock(List memberProductList) { + private void decreaseStock(List memberProductList) { for (MemberProduct memberProduct : memberProductList) { Product product = memberProduct.getProduct(); @@ -136,11 +126,19 @@ private void updateStock(List memberProductList) { throw new GlobalException(PurchaseErrorCode.OUT_OF_STOCK); } else { product.decreaseQuantity(memberProduct.getProductsQuantity()); - productRepository.save(product); } } } + private void increaseStock(Purchase purchase) { + List 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);