RocketMembership관련
- 기존 authorit로 관리하려고 생각했던 RocketMembership을 User table의 rocket_membership을 통해 관리
- 멤버쉽 가입/해제 기능은 하나의 url로 요청을 전송하고 서버에서는 현재 요청한 user의 rocket_membership을 toggle 해준다.
Home Page
- home페이지에 접속했을 때 전체 상품 List를 Pagination해서 가져오는 기능 추가
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class Product extends Base {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "category_id")
private Category type;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "company_id")
private Company company;
@OneToMany(mappedBy = "product")
private Set<ProductOption> optionSet = new HashSet<>();
@OneToMany(mappedBy = "product")
private Set<ClothesOption> clothesOptions = new HashSet<>();
@OneToMany(mappedBy = "product")
private List<ProductImage> thumbnailUrls = new ArrayList<>();
String title;
Integer price;
boolean goldBox;
boolean rocketShipping;
String detailsPageUrl;
}
- product entity를 보면 collection type이 3가지가 존재한다. (option, clothoption, image)
- pageable을 통해 product를 요청하면 limit절이 빠진 상태로 db에 요청하고 전체 데이터를 어플리케이션까지 가져온뒤 서버 메모리에서 limit만큼 가져오게된다. 이럴경우 여러 요청이 동시에 들어올 경우 서버의 메모리 문제로 서버가 다운될 수 있다.
해결한 방법
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
public Page<Product> getAllProductPage(Pageable pageable) { int offset = pageable.getPageNumber() * pageable.getPageSize(); int limit = pageable.getPageSize(); int total = repository.countAll(); List<Product> productList = em.createQuery("SELECT DISTINCT P FROM Product P", Product.class) .setHint(QueryHints.HINT_PASS_DISTINCT_THROUGH, false) .setFirstResult(offset) .setMaxResults(limit) .getResultList(); productList = em.createQuery("SELECT DISTINCT P FROM Product P LEFT JOIN FETCH P.optionSet where P in :products", Product.class) .setParameter("products", productList) .setHint(QueryHints.HINT_PASS_DISTINCT_THROUGH, false) .getResultList(); productList = em.createQuery("SELECT DISTINCT P FROM Product P LEFT JOIN FETCH P.clothesOptions where P in :products", Product.class) .setParameter("products", productList) .setHint(QueryHints.HINT_PASS_DISTINCT_THROUGH, false) .getResultList(); productList = em.createQuery("SELECT DISTINCT P FROM Product P LEFT JOIN FETCH P.thumbnailUrls where P in :products", Product.class) .setParameter("products", productList) .setHint(QueryHints.HINT_PASS_DISTINCT_THROUGH, false) .getResultList(); return new PageImpl<>(productList, pageable, total); }
- query를 나누어 실행하였다. 기존 Pageable만 쓸경우 N + 1문제와 메모리 문제가 발생하는데 처음에 limit절을 포함한 조건에 맞는 product를 가져오고 이후 in절을 사용해 Collection으로 가지고있는 Entity를 추가 조회하면 된다.