ORM: Object-Relational Mapping
JPA: Java Persistence API
public interface ProductRepository extends JpaRepository<Product, Long> {
}
// findById 할 때 Id의 형식 필요함
# 기본 제공 기능
생성 - save
조회 - findAll
전체 개수 조회 - count
삭제 - delete
# ID 외의 필드에 대한 추가 기능은 interface 만 선언해 주면, 구현은 Spring Data JPA 가 대신!!
public interface ProductRepository extends JpaRepository<Product, Long> {
// (1) 회원 ID 로 등록된 상품들 조회
List<Product> findAllByUserId(Long userId);
// (2) 상품명이 title 인 관심상품 1개 조회
Product findByTitle(String title);
// (3) 상품명에 word 가 포함된 모든 상품들 조회
List<Product> findAllByTitleContaining(String word);
// (4) 최저가가 fromPrice ~ toPrice 인 모든 상품들을 조회
List<Product> findAllByLpriceBetween(int fromPrice, int toPrice);
}
Spring Data JPA 의 Query Methods 추가 구현
ProdcutController
# ProductController - 페이징 전
@RestController // JSON으로 데이터를 주고받음을 선언합니다.
public class ProductController {
// 멤버 변수 선언
private final ProductService productService;
// 생성자: ProductController() 가 생성될 때 호출됨
@Autowired
public ProductController(ProductService productService) {
// 멤버 변수 생성
this.productService = productService;
}
// 로그인한 회원이 등록한 상품들 조회
@GetMapping("/api/products")
public List<Product> getProducts(@AuthenticationPrincipal UserDetailsImpl userDetails) {
Long userId = userDetails.getUser().getId();
return productService.getProducts(userId);
}
// 신규 상품 등록
@PostMapping("/api/products")
public Product createProduct(@RequestBody ProductRequestDto requestDto, @AuthenticationPrincipal UserDetailsImpl userDetails) {
// 로그인 되어 있는 ID
Long userId = userDetails.getUser().getId();
Product product = productService.createProduct(requestDto, userId);
// 응답 보내기
return product;
}
// 설정 가격 변경
@PutMapping("/api/products/{id}")
public Long updateProduct(@PathVariable Long id, @RequestBody ProductMypriceRequestDto requestDto) {
Product product = productService.updateProduct(id, requestDto);
return product.getId();
}
}
# 페이징 후
@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;
return productService.getProducts(userId, page , size, sortBy, isAsc);
}
// 신규 상품 등록
@PostMapping("/api/products")
public Product createProduct(@RequestBody ProductRequestDto requestDto, @AuthenticationPrincipal UserDetailsImpl userDetails) {
// 로그인 되어 있는 ID
Long userId = userDetails.getUser().getId();
Product product = productService.createProduct(requestDto, userId);
// 응답 보내기
return product;
}
// 설정 가격 변경
@PutMapping("/api/products/{id}")
public Long updateProduct(@PathVariable Long id, @RequestBody ProductMypriceRequestDto requestDto) {
Product product = productService.updateProduct(id, requestDto);
// 응답 보내기
return product.getId();
}
// (관리자용) 등록된 모든 상품 목록 조회
@Secured("ROLE_ADMIN")
@GetMapping("/api/admin/products")
public Page<Product> getAllProducts(
@RequestParam("page") int page,
@RequestParam("size") int size,
@RequestParam("sortBy") String sortBy,
@RequestParam("isAsc") boolean isAsc
) {
return productService.getAllProducts(page , size, sortBy, isAsc);
}
}
ProductService
# 전
@Service
public class ProductService {
// 멤버 변수 선언
private final ProductRepository productRepository;
// 생성자: ProductService() 가 생성될 때 호출됨
@Autowired
public ProductService(ProductRepository productRepository) {
this.productRepository = productRepository; // 멤버 변수 생성
}
// 회원 ID 로 등록된 모든 상품 조회
public List<Product> getProducts(Long userId) {
return productRepository.findAllByUserId(userId);
}
@Transactional // 메소드 동작이 SQL 쿼리문임을 선언
public Product createProduct(ProductRequestDto requestDto, Long userId){
Product product = new Product(requestDto, userId); // 요청받은 DTO 로 DB에 저장할 객체 만들기
productRepository.save(product);
return product;
}
@Transactional
public Product updateProduct(Long id, ProductMypriceRequestDto requestDto) {
Product product = productRepository.findById(id)
.orElseThrow(() -> new NullPointerException("해당 아이디가 존재하지 않습니다."));
int myPrice = requestDto.getMyprice();
product.updateMyPrice(myPrice);
return product;
}
}
# 후
@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);
}
@Transactional // 메소드 동작이 SQL 쿼리문임을 선언합니다.
public Product createProduct(ProductRequestDto requestDto, Long userId) {
// 요청받은 DTO 로 DB에 저장할 객체 만들기
Product product = new Product(requestDto, userId);
productRepository.save(product);
return product;
}
@Transactional // 메소드 동작이 SQL 쿼리문임을 선언합니다.
public Product updateProduct(Long id, ProductMypriceRequestDto requestDto) {
Product product = productRepository.findById(id).orElseThrow(
() -> new NullPointerException("해당 아이디가 존재하지 않습니다.")
);
// 변경될 관심 가격이 유효한지 확인합니다.
int myPrice = requestDto.getMyprice();
if (myPrice < MIN_PRICE) {
throw new IllegalArgumentException("유효하지 않은 관심 가격입니다. 최소 " + MIN_PRICE + " 원 이상으로 설정해 주세요.");
}
product.updateMyPrice(myPrice);
return product;
}
// 모든 상품 조회 (관리자용)
public Page<Product> getAllProducts(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.findAll(pageable);
}
}
ProductRepository
# 전
public interface ProductRepository extends JpaRepository<Product, Long> {
List<Product> findAllByUserId(Long userId);
}
# 후
public interface ProductRepository extends JpaRepository<Product, Long> {
Page<Product> findAllByUserId(Long userId, Pageable pageable);
}
# FolderCreateRequestDto
@Getter
public class FolderCreateRequestDto {
List<String> folderNames;
}
# FolderController
// 회원이 폴더 추가
@PostMapping("/api/folders")
public List<Folder> addFolders(@RequestBody FolderCreateRequestDto folderCreateRequestDto,
@AuthenticationPrincipal UserDetailsImpl userDetails) {
List<String> folderNames = folderCreateRequestDto.getFolderNames();
return folderService.createFolders(folderNames, userDetails.getUser());
// 예전 Long userId = userDetails.getUser().getId(); -> return 값에 userId 넘겨줌
// 현재 User user = userDetails.getUser();
}
# ProductService
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;
}
# FolderRepository
public interface FolderRepository extends JpaRepository<Folder, Long> {
List<Folder> findAllByUser(User user);
}
# HomeController
@GetMapping("/")
public String home(Model model, @AuthenticationPrincipal UserDetailsImpl userDetails) {
List<Folder> folders = folderService.getFolders(userDetails.getUser());
model.addAttribute("folders", folders);
model.addAttribute("username", userDetails.getUsername());
return "index";
}