25/1/2(목)
List<CategoryResponse>//ex)
[
{
"id": 1,
"name": "카페",
"slug": "cafe",
"imageUrl": "/icons/cafe.png"
},
{
"id": 2,
"name": "상품권",
"slug": "gift-card",
"imageUrl": "/icons/giftcard.png"
},
{
"id": 3,
"name": "치킨",
"slug": "chicken",
"imageUrl": "/icons/chicken.png"
},
{
"id": 4,
"name": "피자·버거",
"slug": "pizza-burger",
"imageUrl": "/icons/pizza.png"
},
{
"id": 5,
"name": "편의점",
"slug": "convenience-store",
"imageUrl": "/icons/convenience.png"
},
{
"id": 6,
"name": "외식",
"slug": "dining",
"imageUrl": "/icons/dining.png"
},
{
"id": 7,
"name": "디저트",
"slug": "dessert",
"imageUrl": "/icons/dessert.png"
}
]
1. DTO 설계
public record CategoryResponse(
Long id,
String name,
String slug,
String imageUrl) {
}
2. API spec 토대로 controller작성
@RestController
public class CategoryRestController {
private final CategoryService categoryService;
public CategoryRestController(CategoryService categoryService) {
this.categoryService = categoryService;
}
@GetMapping("/categories")
public List<CategoryResponse> categoryRead(){
return categoryService.readAll();
}
3. Entity
@Entity
public class Brand {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String imageUrl;
private String guidelines;
@ManyToOne //하나의 카테고리에 여러개의 브랜드가 들어감
private Category category;
public Brand() {
}
public Brand(String name, String imageUrl, String guidelines) {
this.name = name;
this.imageUrl = imageUrl;
this.guidelines = guidelines;
}
public Long getId() {
return id;
}
public String getName() {
return name;
}
public String getImageUrl() {
return imageUrl;
}
public String getGuidelines() {
return guidelines;
}
public Category getCategory() {
return category;
}
}
4. Repository & service 작성
//repository
public interface CategoryRepository extends JpaRepository<Category, Long> {
}
//service
@Service
public class CategoryService {
private final CategoryRepository categoryRepository;
public CategoryService(CategoryRepository categoryRepository) {
this.categoryRepository = categoryRepository;
}
public List<CategoryResponse> readAll() {
List<Category> allCategory = categoryRepository.findAll();
return allCategory.stream().map(category -> new CategoryResponse(
category.getId(),
category.getName(),
category.getSlug(),
category.getImageUrl()))
.toList();
}
전체를 읽어야 하니까 all이 붙어야한다.
[
{
"id": 1,
"name": "메가MGC커피",
"imageUrl": "icons/megacoffee.png"
}
]
1.DTO 설계
public record BrandResponse(
Long id,
String name,
String imageUrl
) {
}
2. Controller
@RestController
public class BrandController {
private final BrandService brandService;
public BrandController(BrandService brandService) {
this.brandService = brandService;
}
@GetMapping("/brands")
public List<BrandResponse> readBrands(@RequestParam String category){
return brandService.read(category);
}
3. Entity 설계
@Entity
public class Brand {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String imageUrl;
@ManyToOne //하나의 카테고리에 여러개의 브랜드가 들어감
private Category category;
public Brand() {
}
public Brand(String name, String imageUrl) {
this.name = name;
this.imageUrl = imageUrl;
}
public Long getId() {
return id;
}
public String getName() {
return name;
}
public String getImageUrl() {
return imageUrl;
}
public Category getCategory() {
return category;
}
}
4. Repository & Service
//repository
public interface BrandRepository extends JpaRepository<Brand, Long> {
}
//Service
@Service
public class BrandService {
private final BrandRepository brandRepository;
public BrandService(BrandRepository brandRepository) {
this.brandRepository = brandRepository;
}
public List<BrandResponse> read(String category) {
List<Brand> categorySlug = brandRepository.findByCategorySlug(category);
return categorySlug.stream().map(brand -> new BrandResponse(
brand.getId(),
brand.getName(),
brand.getImageUrl()
)).toList();
}
나는 category의 Slug를 찾아야한다. 하지만, brandRepository 속에는 slug의 정보가 없으니까 JPA쿼리메서드로 만들어준다.
List<Brand> findByCategorySlug(String slug);
{
"id": 1,
"name": "메가MGC커피",
"imageUrl": ""
}
1. controller수정
@GetMapping("/brands/{brandId}")
public BrandResponse readBrand(@PathVariable Long brandId){
return brandService.oneBrandRead(brandId);
}
2. Service 수정
public BrandResponse oneBrandRead(Long brandId) {
Brand brand = brandRepository.findById(brandId).orElseThrow();
return new BrandResponse(brandId, brand.getName(), brand.getImageUrl());
}
List<ProductResponse>1. DTO 설계
public record ProductResponse(
Long id,
String brandName,
String productName,
int price,
String imageUrl
) {
}
2. controller
@RestController
public class ProductRestController {
private final ProductService productService;
public ProductRestController(ProductService productService) {
this.productService = productService;
}
@GetMapping("/products")
public List<ProductResponse> productOfbrandRead(@RequestParam Long brandId){
return productService.productOfBrand(brandId);
}
}
3. Entity
@Entity
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String brandName;
private String productName;
private int price;
private String imageUrl;
@ManyToOne
private Brand brand;
public Product() {
}
public Product(String brandName, String productName, int price, String imageUrl) {
this.brandName = brandName;
this.productName = productName;
this.price = price;
this.imageUrl = imageUrl;
}
public Long getId() {
return id;
}
public String getBrandName() {
return brandName;
}
public String getProductName() {
return productName;
}
public int getPrice() {
return price;
}
public String getImageUrl() {
return imageUrl;
}
public Brand getBrand() {
return brand;
}
}
4. Repository & Service
//Repository
public interface ProductRepository extends JpaRepository<Product, Long> {
List<Product> findByBrandId(Long brandId);
}
//Service
@Service
public class ProductService {
private final ProductRepository productRepository;
public ProductService(ProductRepository productRepository) {
this.productRepository = productRepository;
}
public List<ProductResponse> productOfBrand(Long brandId) {
List<Product> byBrandId = productRepository.findByBrandId(brandId);
return byBrandId.stream().map(product -> new ProductResponse(
product.getId(),
product.getBrandName(),
product.getProductName(),
product.getPrice(),
product.getImageUrl())).toList();
}
}
brandId를 받아서 brand를 나눠줘야하기 때문에 brandId를 받는 JPA쿼리 메서드를 작성해주었다.
List<ProductResponse>1. controller
@GetMapping("/products/popular")
public List<ProductResponse> popularProduct(@RequestParam(required = false)Long categoryId, Long brandId){
return productService.popularRead(categoryId, brandId);
}
request param으로 받아, category일때와 brand가 들어왔을 때를 구분해준다.
2. service & Repository
public List<ProductResponse> popularRead(Long categoryId, Long brandId) {
if (brandId == null) {
return categoryPopular(categoryId);
}
else return brandPopluar(brandId);
}
brandId가 안들어왔을 땐, categoryId가 들어온거니까, categoryId의 상품을 조회하는 함수로 넘어가고 brandId가 들어왔을 땐, 반대로 실행시켜준다.
private List<ProductResponse> categoryPopular(Long categoryId) {
List<Product> byBrandCategoryId = productRepository.findByBrandCategoryId(categoryId);
return byBrandCategoryId.stream().map(product -> new ProductResponse(
product.getId(),
product.getBrandName(),
product.getProductName(),
product.getPrice(),
product.getImageUrl()
)).toList();
}
private List<ProductResponse> brandPopluar(Long brandId) {
List<Product> byBrandId = productRepository.findByBrandId(brandId);
return byBrandId.stream().map(product -> new ProductResponse(
product.getId(),
product.getBrandName(),
product.getProductName(),
product.getPrice(),
product.getImageUrl()
)).toList();
}
Category는 brand를 참조하고 있기 때문에, brand의 id값을 찾기 위해선 category에 접근한 JPA쿼리 메서드를 Repository에 저장해준다.
List<Product> findByBrandCategoryId(Long categoryId);
그걸 받아서 사용한다.
{
"productId": 1,
"productName": "(ICE)아메리카노",
"price": 2000,
"brand": {
"id": 1,
"name": "메가MGC커피",
"guidelines": "#사용처 - 전국 메가MGC커피 매장에서 사용 가능합니다. #제한사항 - 사진은 이미지 컷이므로 실제와 다를 수 있습니다. #유의사항 - *지급보증 : 본 상품은 별도의 지급보증 및 피해보상보험계약체결 없이 자체 신용으로 발행되었습니다.",
},
"expirationDays": 366
}
1. DTO구현
public record detailProductResponse(
Long productId,
String productName,
int price,
int expirationDays,
Brand brand
) {
}
2.Controller구현
@GetMapping("/products/{productId}")
public detailProductResponse detailRead(@PathVariable Long productId){
return productService.detailRead(productId);
}
3. Service구현
public detailProductResponse detailRead(Long productId) {
Product product = productRepository.findById(productId).orElseThrow();
return new detailProductResponse(
productId,
product.getProductName(),
product.getPrice(),
product.getExpirationDays(),
new Brand(
product.getBrandName(),
product.getImageUrl(),
product.getGuidelines())
);
}
😐 느낀점
이제 좀 알 것같다~!~!
1:N관계에서도 관계매핑하는 방법도 익숙해진 것 같고, 이제는 조금 부드러운 코딩이 된 것 같다.