고을마을 : 나의 코딩 이야기

항해99 24일차 TIL[@Transactional, 페이징 및 정렬 설계] 본문

항해99 7기/TIL(Today I Learned)

항해99 24일차 TIL[@Transactional, 페이징 및 정렬 설계]

고을마을 2022. 6. 4. 01:59

2022년 6월 3일. 항해 24일차.

오늘부터 주특기 심화주차.

 

과제에 끌려다니기 보단 기초부터 차근차근히 다져나가기로 했다.

장기적으로 봤을때 그게 더 나에게 이득일테니...

 


나는

@Transactional

"SQL 쿼리가 일어나야함을 스프링에게 알려주는 것"으로만 알고 있었다.

 

public Users updateUser1() {
// 테스트 회원 "user1" 생성
        Users user = new Users("user1", "RM", "고기");
// 회원 "user1" 객체를 영속화
        Users savedUser1 = userRepository.save(user);

// 회원의 nickname 변경
        savedUser1.setNickname("남준이");
// 회원의 favoriteFood 변경
        savedUser1.setFavoriteFood("육회");

// user1 을 저장
        Users savedUser2 = userRepository.save(savedUser1);
        assert(savedUser1 == savedUser2);

        return savedUser2;
    }

    @Transactional
    public Users updateUser2() {
// 테스트 회원 "user1" 생성
// 회원 "user1" 객체 추가
        Users user = new Users("user1", "진", "꽃등심");
// 회원 "user1" 객체를 영속화
        Users savedUser = userRepository.save(user);
// 회원의 nickname 변경
        savedUser.setNickname("월드와이드핸섬 진");
// 회원의 favoriteFood 변경
        savedUser.setFavoriteFood("까르보나라");
        return savedUser;
    }
}

 

위의 코드는 영속화를 위한 코드이다.

updateUser1은 @Transactional을 활용하지 않은 코드인데set을 하고나서 db에 넘겨주기 위해 바뀐 내용이 담긴 saveduser1을 saveduser2에 userRepository.save() 함수를 설정해준 후 return 해줬다.

 

반면uadateUser2는 @Tansatctional을 활용한 코드이다.set을 하고나서 바로  savedUser로 리턴해줬다.

굳이 userRepository.save() 함수를 호출하지 않아도, 함수가 끝나는 시점에 변경된 부분을 알아서 업데이트 해준다!

 

 


페이징 및 정렬 설계

@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;
    return productService.getProducts(userId, page, size, sortBy, isAsc);
}

 

클라이언트에서 서버로 받아올때 아래의 사항을 고려해서 controller를 작성해봤다.. 

  1. page : 조회할 페이지 번호 (1부터 시작)
  2. size : 한 페이지에 보여줄 상품 개수 (10개로 고정!)
  3. sortBy (정렬 항목)
    1. id : Product 테이블의 id
    2. title : 상품명
    3. lprice : 최저가
    4. createdAt : 생성일 (보통 id 와 동일)
  4. isAsc (오름차순?)
    1. true: 오름차순 (asc)
    2. false : 내림차순 (desc)

 

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);
}

 

Spring Boot JPA를 이용한 Pageable을 넣어줬다. 

List<Product>를 Page<Product>로 바꿔줬다.