반응형
1. 페이징(Paging)
- 페이징은 모든 데이터를 무한 스크롤하여 보는 것이 아니라 페이지로 나눠서 데이터를 나눠서 볼 수 있는 것이다. 다음 사진처럼 데이터가 페이지마다 나눠져서 볼 수 있는 방식이다.
나만의 셀렉샵에서 페이징 처리하는 부분을 추가해보겠다. ProcductController 에서 "페이지 번호, 각 페이지의 상품 수, 정렬 방식, 오름차순 여부, 회원 정보" 를 입력받아 요쳥에 맞는 상품들을 ProductService 를 통해 조회한다. Pageable 은 쉽게 페이징 처리를 할 수 있도록 도와준다.
@RestController // JSON으로 데이터를 주고받음을 선언합니다.
public class ProductController {
// 멤버 변수 선언
private final ProductService productService;
// 생성자: ProductController() 가 생성될 때 호출됨
@Autowired
public ProductController(ProductService productService) {
// 멤버 변수 생성
this.productService = productService;
}
// 로그인한 회원이 등록한 상품들 조회
@GetMapping("/api/products")
public Page<Product> getProducts(
@RequestParam("page") int page,
@RequestParam("size") int size,
@RequestParam("sortBy") String sortBy,
@RequestParam("isAsc") boolean isAsc,
@AuthenticationPrincipal UserDetailsImpl userDetails
) {
Long userId = userDetails.getUser().getId();
page = page - 1; // 서버에서는 페이지가 0부터 시작
return productService.getProducts(userId, page , size, sortBy, isAsc);
}
}
@Service
public class ProductService {
// 멤버 변수 선언
private final ProductRepository productRepository;
private static final int MIN_PRICE = 100;
// 생성자: ProductService() 가 생성될 때 호출됨
@Autowired
public ProductService(ProductRepository productRepository) {
// 멤버 변수 생성
this.productRepository = productRepository;
}
public Page<Product> getProducts(Long userId, int page, int size, String sortBy, boolean isAsc) {
Sort.Direction direction = isAsc ? Sort.Direction.ASC : Sort.Direction.DESC;
Sort sort = Sort.by(direction, sortBy);
Pageable pageable = PageRequest.of(page, size, sort);
return productRepository.findAllByUserId(userId, pageable);
}
}
public interface ProductRepository extends JpaRepository<Product, Long> {
Page<Product> findAllByUserId(Long userId, Pageable pageable);
}
2. JPA 연관관계
- DB의 연관관계는 JPA 연관관계로 표현할 수 있다. 연관관계는 다음과 같은 예시처럼 만들어줄 수 있다.
관계 | 코드 | 연관관계 | 예시 |
1 : N (일대다) | @OneToMany | Order(1) : Food(N) | 하나의 주문에 여러 음식 선택 가능 |
N : 1 (다대일) | @ManyToOne | Owner(N) : Restaurant(1) | 하나의 음식점을 여러 주인이 소유 가능 |
1 : 1 (일대일) | @OneToOne | Order(1) : Coupon(1) | 하나의 주문에 하나의 쿠폰만 사용 가능 |
N : M (다대다) | @ManyToMany | User(N) : Restaurant(M) | 고객은 여러 음식점 찜 가능, 음식점은 여러 고객에게 찜 가능 |
JPA 연관관계를 사용하여 나만의 셀렉샵에 회원별 폴더 기능을 추가해보겠다. 회원(User)과 폴더(Folder)는 1:N 관계이므로 Folder에 @ManyToOne을 사용하여 관계를 만들어준다.
@Setter
@Getter // get 함수를 일괄적으로 만들어줍니다.
@NoArgsConstructor // 기본 생성자를 만들어줍니다.
@Entity // DB 테이블 역할을 합니다.
public class Folder extends Timestamped {
public Folder(String name, User user) {
this.name = name;
this.user = user;
}
// ID가 자동으로 생성 및 증가합니다.
@GeneratedValue(strategy = GenerationType.AUTO)
@Id
private Long id;
// 반드시 값을 가지도록 합니다.
@Column(nullable = false)
private String name;
@ManyToOne
@JoinColumn(nullable = false)
private User user;
}
회원이 폴더를 조회하고 폴더를 생성할 수 있도록 FolderControlller, FolderService, FolderRepository를 다음과 같이 생성한다.
@RestController
public class FolderController {
// 멤버 변수 선언
private final FolderService folderService;
@Autowired
public FolderController(FolderService folderService) {
// 멤버 변수 생성
this.folderService = folderService;
}
// 회원이 등록한 모든 폴더 조회
@GetMapping("/api/folders")
public List<Folder> getFolders(@AuthenticationPrincipal UserDetailsImpl userDetails) {
return folderService.getFolders(userDetails.getUser());
}
// 회원이 폴더 추가
@PostMapping("/api/folders")
public List<Folder> addFolders(@RequestBody FolderCreateRequestDto folderCreateRequestDto, @AuthenticationPrincipal UserDetailsImpl userDetails) {
List<String> folderNames = folderCreateRequestDto.getFolderNames();
return folderService.createFolders(folderNames, userDetails.getUser());
}
}
@Service
public class FolderService {
// 멤버 변수 선언
private final FolderRepository folderRepository;
// 생성자: ProductFolderService() 가 생성될 때 호출됨
@Autowired
public FolderService(FolderRepository folderRepository) {
// 멤버 변수 생성
this.folderRepository = folderRepository;
}
// 회원 ID 로 등록된 모든 폴더 조회
public List<Folder> getFolders(User user) {
return folderRepository.findAllByUser(user);
}
public List<Folder> createFolders(List<String> folderNameList, User user) {
List<Folder> folderList = new ArrayList<>();
for (String folderName : folderNameList) {
Folder folder = new Folder(folderName, user);
folderList.add(folder);
}
folderList = folderRepository.saveAll(folderList);
return folderList;
}
}
public interface FolderRepository extends JpaRepository<Folder, Long> {
List<Folder> findAllByUser(User user);
}
반응형
'Back-end > Spring' 카테고리의 다른 글
객체 지향 프로그래밍과 SOLID (0) | 2022.01.08 |
---|---|
[SpringBoot] 10주차 스터디(AOP, 트랜잭션) (0) | 2021.10.23 |
[SpringBoot] 8주차 스터디 (단위테스트, 통합테스트) (0) | 2021.10.07 |
[SpringBoot] 7주차 스터디 ② (OAuth, 카카오 로그인) (0) | 2021.10.02 |
[SpringBoot] 7주차 스터디 ① (스프링 시큐리티) (0) | 2021.10.02 |