From 5647f761776ff9643814d3661430407dafdbd37b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EC=84=B1?= <166998868+castlekimdev@users.noreply.github.com> Date: Fri, 28 Jun 2024 15:35:11 +0900 Subject: [PATCH 01/20] =?UTF-8?q?docs:=20=EA=B5=AC=ED=98=84=ED=95=A0=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EB=AA=A9=EB=A1=9D=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index cafde8a2c..acb47fce0 100644 --- a/README.md +++ b/README.md @@ -1 +1,31 @@ -# spring-gift-product \ No newline at end of file +# spring-gift-product + +# 1단계 + +## 구현할 기능 + +* 상품 정보를 담기 위한 Product Class 구현 +* 상품 전체 조회 API +* 상품 단건 조회 API +* 상품 추가 API +* 상품 수정 API +* 상품 삭제 API + +# 2단계 + +## 구현할 기능 + +* [Controller] + * 상품 관리 페이지 응답용 컨트롤러 구현 +* [View] + * 상품 전체 조회 화면 + * 상품 추가 버튼 구현 + * 상품 수정 버튼 구현 + * 상품 삭제 버튼 구현 + +# 3단계 + +## 구현할 기능 + +* h2 데이터베이스 연동 +* 상품 정보를 저장하기 위한 ProductRepository 구현 From 8eb5891c8404509265107a1399ebbbca84f310d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EC=84=B1?= <166998868+castlekimdev@users.noreply.github.com> Date: Fri, 28 Jun 2024 15:35:34 +0900 Subject: [PATCH 02/20] =?UTF-8?q?feat:=20=EC=83=81=ED=92=88=20=ED=81=B4?= =?UTF-8?q?=EB=9E=98=EC=8A=A4=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/gift/domain/Product.java | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 src/main/java/gift/domain/Product.java diff --git a/src/main/java/gift/domain/Product.java b/src/main/java/gift/domain/Product.java new file mode 100644 index 000000000..456bc75d1 --- /dev/null +++ b/src/main/java/gift/domain/Product.java @@ -0,0 +1,10 @@ +package gift.domain; + +public record Product( + Long id, + String name, + Integer price, + String imageUrl +) { + +} From fac0838c95c7d711fbde3d1c342f605fd11a6b21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EC=84=B1?= <166998868+castlekimdev@users.noreply.github.com> Date: Fri, 28 Jun 2024 15:36:24 +0900 Subject: [PATCH 03/20] =?UTF-8?q?feat:=20=EC=83=81=ED=92=88=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20API=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gift/controller/ProductController.java | 95 +++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 src/main/java/gift/controller/ProductController.java diff --git a/src/main/java/gift/controller/ProductController.java b/src/main/java/gift/controller/ProductController.java new file mode 100644 index 000000000..7476a1b4c --- /dev/null +++ b/src/main/java/gift/controller/ProductController.java @@ -0,0 +1,95 @@ +package gift.controller; + +import gift.controller.dto.ProductCreateRequestDto; +import gift.controller.dto.ProductResponseDto; +import gift.controller.dto.ProductUpdateRequestDto; +import gift.domain.Product; +import gift.repository.ProductRepository; +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class ProductController { + + private final ProductRepository products; + + @Autowired + public ProductController(ProductRepository products) { + this.products = products; + } + + @GetMapping("/products") + public List getAllProducts() { + return products + .findAll() + .stream() + .map(ProductResponseDto::from) + .toList(); + } + + @GetMapping("/products/{id}") + public ProductResponseDto getProduct(@PathVariable Long id) { + return ProductResponseDto.from(products.get(id)); + } + + @PostMapping("/products") + public void addProduct( + @RequestBody ProductCreateRequestDto productCreateRequest + ) { + Product product = productOf(productCreateRequest); + products.save(product); + } + + @PutMapping("/products/{id}") + public void updateProduct( + @PathVariable Long id, + @RequestBody ProductUpdateRequestDto productUpdateRequest + ) { + Product originalProduct = products.get(id); + if (originalProduct == null) { + throw new RuntimeException("Product not found"); + } + Product updatedProduct = applyUpdate(originalProduct, productUpdateRequest); + products.save(updatedProduct); + } + + @DeleteMapping("/products/{id}") + public void deleteProduct(@PathVariable Long id) { + products.remove(id); + } + + private Product productOf(ProductCreateRequestDto productCreateRequest) { + return new Product( + 0L, + productCreateRequest.name(), + productCreateRequest.price(), + productCreateRequest.imageUrl() + ); + } + + private Product applyUpdate(Product originalProduct, + ProductUpdateRequestDto productUpdateRequest) { + String name = originalProduct.name(); + if (productUpdateRequest.name() != null) { + name = productUpdateRequest.name(); + } + + Integer price = originalProduct.price(); + if (productUpdateRequest.price() != null) { + price = productUpdateRequest.price(); + } + + String imageUrl = originalProduct.imageUrl(); + if (productUpdateRequest.imageUrl() != null) { + imageUrl = productUpdateRequest.imageUrl(); + } + return new Product(originalProduct.id(), name, price, imageUrl); + } +} From aeccfc761c317b33bd47215f6ece6752941bed2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EC=84=B1?= <166998868+castlekimdev@users.noreply.github.com> Date: Fri, 28 Jun 2024 15:36:53 +0900 Subject: [PATCH 04/20] =?UTF-8?q?feat:=20=EC=83=81=ED=92=88=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20=EC=88=98=EC=A0=95=20=EC=82=AD=EC=A0=9C=20DTO=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/dto/ProductCreateRequestDto.java | 8 ++++++++ .../gift/controller/dto/ProductResponseDto.java | 16 ++++++++++++++++ .../controller/dto/ProductUpdateRequestDto.java | 9 +++++++++ 3 files changed, 33 insertions(+) create mode 100644 src/main/java/gift/controller/dto/ProductCreateRequestDto.java create mode 100644 src/main/java/gift/controller/dto/ProductResponseDto.java create mode 100644 src/main/java/gift/controller/dto/ProductUpdateRequestDto.java diff --git a/src/main/java/gift/controller/dto/ProductCreateRequestDto.java b/src/main/java/gift/controller/dto/ProductCreateRequestDto.java new file mode 100644 index 000000000..83d3bdb39 --- /dev/null +++ b/src/main/java/gift/controller/dto/ProductCreateRequestDto.java @@ -0,0 +1,8 @@ +package gift.controller.dto; + +public record ProductCreateRequestDto( + String name, + Integer price, + String imageUrl +) { +} \ No newline at end of file diff --git a/src/main/java/gift/controller/dto/ProductResponseDto.java b/src/main/java/gift/controller/dto/ProductResponseDto.java new file mode 100644 index 000000000..8f51d826b --- /dev/null +++ b/src/main/java/gift/controller/dto/ProductResponseDto.java @@ -0,0 +1,16 @@ +package gift.controller.dto; + +import gift.domain.Product; + +public record ProductResponseDto( + Long id, + String name, + Integer price, + String imageUrl +) { + + public static ProductResponseDto from(Product product) { + return new ProductResponseDto(product.id(), product.name(), product.price(), + product.imageUrl()); + } +} diff --git a/src/main/java/gift/controller/dto/ProductUpdateRequestDto.java b/src/main/java/gift/controller/dto/ProductUpdateRequestDto.java new file mode 100644 index 000000000..012af18ba --- /dev/null +++ b/src/main/java/gift/controller/dto/ProductUpdateRequestDto.java @@ -0,0 +1,9 @@ +package gift.controller.dto; + +public record ProductUpdateRequestDto( + String name, + Integer price, + String imageUrl +) { + +} From 7811777932f9d7c7f8a1134f1dd6cd645b60946c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EC=84=B1?= <166998868+castlekimdev@users.noreply.github.com> Date: Fri, 28 Jun 2024 15:37:27 +0900 Subject: [PATCH 05/20] =?UTF-8?q?feat:=20=EC=83=81=ED=92=88=20=EA=B4=80?= =?UTF-8?q?=EB=A6=AC=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=9D=91=EB=8B=B5?= =?UTF-8?q?=EC=9A=A9=20=EC=BB=A8=ED=8A=B8=EB=A1=A4=EB=9F=AC=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/gift/controller/AdminController.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/main/java/gift/controller/AdminController.java diff --git a/src/main/java/gift/controller/AdminController.java b/src/main/java/gift/controller/AdminController.java new file mode 100644 index 000000000..3743df66f --- /dev/null +++ b/src/main/java/gift/controller/AdminController.java @@ -0,0 +1,13 @@ +package gift.controller; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; + +@Controller +public class AdminController { + + @GetMapping("/admin") + public String admin() { + return "admin"; + } +} From 78357b18918781f4c60f6e9ad3241bbbf0320339 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EC=84=B1?= <166998868+castlekimdev@users.noreply.github.com> Date: Fri, 28 Jun 2024 15:37:54 +0900 Subject: [PATCH 06/20] =?UTF-8?q?feat:=20=EC=96=B4=EB=93=9C=EB=AF=BC=20?= =?UTF-8?q?=EC=83=81=ED=92=88=20=EA=B4=80=EB=A6=AC=20=ED=99=94=EB=A9=B4=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/templates/admin.html | 98 +++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 src/main/resources/templates/admin.html diff --git a/src/main/resources/templates/admin.html b/src/main/resources/templates/admin.html new file mode 100644 index 000000000..52535a8a8 --- /dev/null +++ b/src/main/resources/templates/admin.html @@ -0,0 +1,98 @@ + + + + + Manage Products + + + +
+

Manage Products

+
+ +
+ + + + + + + + + + + + +
IDNamePriceImage URLActions
+
+ + + + From 022cb5cd411eef9a9acd1581ca5d50d6202bdc03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EC=84=B1?= <166998868+castlekimdev@users.noreply.github.com> Date: Fri, 28 Jun 2024 15:38:05 +0900 Subject: [PATCH 07/20] =?UTF-8?q?feat:=20h2=20=EB=8D=B0=EC=9D=B4=ED=84=B0?= =?UTF-8?q?=EB=B2=A0=EC=9D=B4=EC=8A=A4=20ddl=20=EC=A0=95=EC=9D=98=20?= =?UTF-8?q?=EB=B0=8F=20=EC=97=B0=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/static/schma.sql | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 src/main/resources/static/schma.sql diff --git a/src/main/resources/static/schma.sql b/src/main/resources/static/schma.sql new file mode 100644 index 000000000..04821ad9d --- /dev/null +++ b/src/main/resources/static/schma.sql @@ -0,0 +1,6 @@ +create table `products` ( + `id` bigint auto_increment primary key, + `name` varchar(255) not null, + `price` int not null, + `image_url` varchar(255) not null +); From 4bdcf3542f1119b17b85066354eb96b116b21593 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EC=84=B1?= <166998868+castlekimdev@users.noreply.github.com> Date: Fri, 28 Jun 2024 15:39:02 +0900 Subject: [PATCH 08/20] =?UTF-8?q?feat:=20product=20repository=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gift/repository/ProductRepository.java | 19 +++++ .../repository/ProductRepositoryImpl.java | 74 +++++++++++++++++++ 2 files changed, 93 insertions(+) create mode 100644 src/main/java/gift/repository/ProductRepository.java create mode 100644 src/main/java/gift/repository/ProductRepositoryImpl.java diff --git a/src/main/java/gift/repository/ProductRepository.java b/src/main/java/gift/repository/ProductRepository.java new file mode 100644 index 000000000..d44a6f447 --- /dev/null +++ b/src/main/java/gift/repository/ProductRepository.java @@ -0,0 +1,19 @@ +package gift.repository; + +import gift.domain.Product; +import java.util.List; + +public interface ProductRepository { + + Product get(Long id); + + boolean exists(Long id); + + void save(Product product); + + int size(); + + List findAll(); + + void remove(Long id); +} diff --git a/src/main/java/gift/repository/ProductRepositoryImpl.java b/src/main/java/gift/repository/ProductRepositoryImpl.java new file mode 100644 index 000000000..6fddb861d --- /dev/null +++ b/src/main/java/gift/repository/ProductRepositoryImpl.java @@ -0,0 +1,74 @@ +package gift.repository; + +import gift.domain.Product; +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.stereotype.Repository; + +@Repository +public class ProductRepositoryImpl implements ProductRepository { + + private final JdbcTemplate jdbcTemplate; + + private final RowMapper rowMapper = (rs, rowNum) -> new Product( + rs.getLong("id"), + rs.getString("name"), + rs.getInt("price"), + rs.getString("image_url") + ); + + @Autowired + public ProductRepositoryImpl(JdbcTemplate jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; + } + + @Override + public Product get(Long id) { + String sql = "SELECT * FROM `products` WHERE `id` = ?"; + return jdbcTemplate.queryForObject(sql, rowMapper, id); + } + + @Override + public boolean exists(Long id) { + String sql = "SELECT COUNT(`id`) FROM `products` WHERE `id` = ?"; + Integer result = jdbcTemplate.queryForObject(sql, Integer.class, id); + return result != null && result > 0; + } + + @Override + public void save(Product product) { + if (exists(product.id())) { + String sql = "UPDATE `products` SET `name` = ?, `price` = ?, `image_url` = ? WHERE `id` = ?"; + jdbcTemplate.update(sql, product.name(), product.price(), product.imageUrl(), + product.id()); + return; + } + String sql = "INSERT INTO `products` (`name`, `price`, `image_url`) VALUES (?, ?, ?)"; + jdbcTemplate.update(sql, product.name(), product.price(), product.imageUrl()); + } + + @Override + public int size() { + String sql = "SELECT COUNT(*) FROM `products`"; + Integer result = jdbcTemplate.queryForObject(sql, Integer.class); + if (result == null) { + return 0; + } + return result; + } + + @Override + public List findAll() { + String sql = "SELECT * FROM `products`"; + List products = jdbcTemplate.query(sql, rowMapper); + return List.copyOf(products); + } + + @Override + public void remove(Long id) { + String sql = "DELETE FROM `products` WHERE `id` = ?"; + jdbcTemplate.update(sql, id); + } +} From 54ea3aa0346c370003b3e5ae0805a554e9aa4091 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EC=84=B1?= <166998868+castlekimdev@users.noreply.github.com> Date: Sun, 30 Jun 2024 22:01:35 +0900 Subject: [PATCH 09/20] =?UTF-8?q?refactor:=20=EB=8D=94=20=EC=A7=81?= =?UTF-8?q?=EA=B4=80=EC=A0=81=EC=9D=B8=20=EB=84=A4=EC=9D=B4=EB=B0=8D?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD=20(`productRepository?= =?UTF-8?q?=20`)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gift/controller/ProductController.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/java/gift/controller/ProductController.java b/src/main/java/gift/controller/ProductController.java index 7476a1b4c..a5e3cd949 100644 --- a/src/main/java/gift/controller/ProductController.java +++ b/src/main/java/gift/controller/ProductController.java @@ -18,16 +18,16 @@ @RestController public class ProductController { - private final ProductRepository products; + private final ProductRepository productRepository; @Autowired - public ProductController(ProductRepository products) { - this.products = products; + public ProductController(ProductRepository productRepository) { + this.productRepository = productRepository; } @GetMapping("/products") public List getAllProducts() { - return products + return productRepository .findAll() .stream() .map(ProductResponseDto::from) @@ -36,7 +36,7 @@ public List getAllProducts() { @GetMapping("/products/{id}") public ProductResponseDto getProduct(@PathVariable Long id) { - return ProductResponseDto.from(products.get(id)); + return ProductResponseDto.from(productRepository.get(id)); } @PostMapping("/products") @@ -44,7 +44,7 @@ public void addProduct( @RequestBody ProductCreateRequestDto productCreateRequest ) { Product product = productOf(productCreateRequest); - products.save(product); + productRepository.save(product); } @PutMapping("/products/{id}") @@ -52,17 +52,17 @@ public void updateProduct( @PathVariable Long id, @RequestBody ProductUpdateRequestDto productUpdateRequest ) { - Product originalProduct = products.get(id); + Product originalProduct = productRepository.get(id); if (originalProduct == null) { throw new RuntimeException("Product not found"); } Product updatedProduct = applyUpdate(originalProduct, productUpdateRequest); - products.save(updatedProduct); + productRepository.save(updatedProduct); } @DeleteMapping("/products/{id}") public void deleteProduct(@PathVariable Long id) { - products.remove(id); + productRepository.remove(id); } private Product productOf(ProductCreateRequestDto productCreateRequest) { From 315c4fadacfca518597c08b0e43c78dccc49414e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EC=84=B1?= <166998868+castlekimdev@users.noreply.github.com> Date: Sun, 30 Jun 2024 22:04:38 +0900 Subject: [PATCH 10/20] =?UTF-8?q?refactor:=20`/products`=EB=A1=9C=20?= =?UTF-8?q?=EA=B3=B5=ED=86=B5=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/gift/controller/ProductController.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/gift/controller/ProductController.java b/src/main/java/gift/controller/ProductController.java index a5e3cd949..7d1084b28 100644 --- a/src/main/java/gift/controller/ProductController.java +++ b/src/main/java/gift/controller/ProductController.java @@ -15,7 +15,7 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; -@RestController +@RestController("/products") public class ProductController { private final ProductRepository productRepository; @@ -25,7 +25,7 @@ public ProductController(ProductRepository productRepository) { this.productRepository = productRepository; } - @GetMapping("/products") + @GetMapping public List getAllProducts() { return productRepository .findAll() @@ -34,12 +34,12 @@ public List getAllProducts() { .toList(); } - @GetMapping("/products/{id}") + @GetMapping("/{id}") public ProductResponseDto getProduct(@PathVariable Long id) { return ProductResponseDto.from(productRepository.get(id)); } - @PostMapping("/products") + @PostMapping public void addProduct( @RequestBody ProductCreateRequestDto productCreateRequest ) { @@ -47,7 +47,7 @@ public void addProduct( productRepository.save(product); } - @PutMapping("/products/{id}") + @PutMapping("{id}") public void updateProduct( @PathVariable Long id, @RequestBody ProductUpdateRequestDto productUpdateRequest @@ -60,7 +60,7 @@ public void updateProduct( productRepository.save(updatedProduct); } - @DeleteMapping("/products/{id}") + @DeleteMapping("/{id}") public void deleteProduct(@PathVariable Long id) { productRepository.remove(id); } From 32562c04558081b0e413d951ea7c29125a121320 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EC=84=B1?= <166998868+castlekimdev@users.noreply.github.com> Date: Sun, 30 Jun 2024 22:52:44 +0900 Subject: [PATCH 11/20] =?UTF-8?q?refactor:=20=EB=8F=84=EB=A9=94=EC=9D=B8?= =?UTF-8?q?=20=EA=B0=9D=EC=B2=B4=20`record`=20=EB=8C=80=EC=8B=A0=20`class`?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/gift/domain/Product.java | 82 ++++++++++++++++++++++++-- 1 file changed, 76 insertions(+), 6 deletions(-) diff --git a/src/main/java/gift/domain/Product.java b/src/main/java/gift/domain/Product.java index 456bc75d1..54d6039eb 100644 --- a/src/main/java/gift/domain/Product.java +++ b/src/main/java/gift/domain/Product.java @@ -1,10 +1,80 @@ package gift.domain; -public record Product( - Long id, - String name, - Integer price, - String imageUrl -) { +import java.util.Objects; +public class Product { + + private Long id; + private String name; + private Integer price; + private String imageUrl; + + public Product(Long id, String name, Integer price, String imageUrl) { + this.id = id; + this.name = name; + this.price = price; + this.imageUrl = imageUrl; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Integer getPrice() { + return price; + } + + public void setPrice(Integer price) { + this.price = price; + } + + public String getImageUrl() { + return imageUrl; + } + + public void setImageUrl(String imageUrl) { + this.imageUrl = imageUrl; + } + + @Override + public String toString() { + return "Product{" + + "id=" + id + + ", name='" + name + '\'' + + ", price=" + price + + ", imageUrl='" + imageUrl + '\'' + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Product product = (Product) o; + return Objects.equals(id, product.id) && + Objects.equals(name, product.name) && + Objects.equals(price, product.price) && + Objects.equals(imageUrl, product.imageUrl); + } + + @Override + public int hashCode() { + return Objects.hash(id, name, price, imageUrl); + } } From 37923e7bd303c941cdaaecb5f92255fe682ae488 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EC=84=B1?= <166998868+castlekimdev@users.noreply.github.com> Date: Sun, 30 Jun 2024 23:01:02 +0900 Subject: [PATCH 12/20] =?UTF-8?q?refactor:=20`Repository`=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=ED=95=A8=EC=88=98=20=EB=A6=AC=ED=84=B4=EA=B0=92=20?= =?UTF-8?q?Optional=20=ED=95=98=EA=B2=8C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/gift/controller/ProductController.java | 14 ++++++++------ src/main/java/gift/domain/Product.java | 8 ++++---- .../java/gift/repository/ProductRepository.java | 3 ++- .../gift/repository/ProductRepositoryImpl.java | 10 ++++++++-- 4 files changed, 22 insertions(+), 13 deletions(-) diff --git a/src/main/java/gift/controller/ProductController.java b/src/main/java/gift/controller/ProductController.java index 7d1084b28..495314d3e 100644 --- a/src/main/java/gift/controller/ProductController.java +++ b/src/main/java/gift/controller/ProductController.java @@ -36,9 +36,12 @@ public List getAllProducts() { @GetMapping("/{id}") public ProductResponseDto getProduct(@PathVariable Long id) { - return ProductResponseDto.from(productRepository.get(id)); + Product product = productRepository.findById(id) + .orElseThrow(() -> new RuntimeException("Product not found")); + return ProductResponseDto.from(product); } + @PostMapping public void addProduct( @RequestBody ProductCreateRequestDto productCreateRequest @@ -47,15 +50,14 @@ public void addProduct( productRepository.save(product); } - @PutMapping("{id}") + @PutMapping("/{id}") public void updateProduct( @PathVariable Long id, @RequestBody ProductUpdateRequestDto productUpdateRequest ) { - Product originalProduct = productRepository.get(id); - if (originalProduct == null) { - throw new RuntimeException("Product not found"); - } + Product originalProduct = productRepository.findById(id) + .orElseThrow(() -> new RuntimeException("Product not found")); + Product updatedProduct = applyUpdate(originalProduct, productUpdateRequest); productRepository.save(updatedProduct); } diff --git a/src/main/java/gift/domain/Product.java b/src/main/java/gift/domain/Product.java index 54d6039eb..e1cb95473 100644 --- a/src/main/java/gift/domain/Product.java +++ b/src/main/java/gift/domain/Product.java @@ -16,7 +16,7 @@ public Product(Long id, String name, Integer price, String imageUrl) { this.imageUrl = imageUrl; } - public Long getId() { + public Long id() { return id; } @@ -24,7 +24,7 @@ public void setId(Long id) { this.id = id; } - public String getName() { + public String name() { return name; } @@ -32,7 +32,7 @@ public void setName(String name) { this.name = name; } - public Integer getPrice() { + public Integer price() { return price; } @@ -40,7 +40,7 @@ public void setPrice(Integer price) { this.price = price; } - public String getImageUrl() { + public String imageUrl() { return imageUrl; } diff --git a/src/main/java/gift/repository/ProductRepository.java b/src/main/java/gift/repository/ProductRepository.java index d44a6f447..a8a8fd04c 100644 --- a/src/main/java/gift/repository/ProductRepository.java +++ b/src/main/java/gift/repository/ProductRepository.java @@ -2,10 +2,11 @@ import gift.domain.Product; import java.util.List; +import java.util.Optional; public interface ProductRepository { - Product get(Long id); + Optional findById(Long id); boolean exists(Long id); diff --git a/src/main/java/gift/repository/ProductRepositoryImpl.java b/src/main/java/gift/repository/ProductRepositoryImpl.java index 6fddb861d..6a8304422 100644 --- a/src/main/java/gift/repository/ProductRepositoryImpl.java +++ b/src/main/java/gift/repository/ProductRepositoryImpl.java @@ -2,6 +2,7 @@ import gift.domain.Product; import java.util.List; +import java.util.Optional; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; @@ -25,9 +26,14 @@ public ProductRepositoryImpl(JdbcTemplate jdbcTemplate) { } @Override - public Product get(Long id) { + public Optional findById(Long id) { String sql = "SELECT * FROM `products` WHERE `id` = ?"; - return jdbcTemplate.queryForObject(sql, rowMapper, id); + try { + Product product = jdbcTemplate.queryForObject(sql, rowMapper, id); + return Optional.ofNullable(product); + } catch (Exception e) { + return Optional.empty(); + } } @Override From a3f91e11eb63ca32b612cad3d851a69c9e7320a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EC=84=B1?= <166998868+castlekimdev@users.noreply.github.com> Date: Sun, 30 Jun 2024 23:11:40 +0900 Subject: [PATCH 13/20] =?UTF-8?q?refactor:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EC=96=B4=EB=85=B8=ED=85=8C=EC=9D=B4=EC=85=98=20`@A?= =?UTF-8?q?utowired`=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/gift/controller/ProductController.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/gift/controller/ProductController.java b/src/main/java/gift/controller/ProductController.java index 495314d3e..762e2c0a7 100644 --- a/src/main/java/gift/controller/ProductController.java +++ b/src/main/java/gift/controller/ProductController.java @@ -6,7 +6,6 @@ import gift.domain.Product; import gift.repository.ProductRepository; import java.util.List; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -20,7 +19,6 @@ public class ProductController { private final ProductRepository productRepository; - @Autowired public ProductController(ProductRepository productRepository) { this.productRepository = productRepository; } From 7d500f5b12c82158897c54ba2e6de78889f99753 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EC=84=B1?= <166998868+castlekimdev@users.noreply.github.com> Date: Sun, 30 Jun 2024 23:32:25 +0900 Subject: [PATCH 14/20] =?UTF-8?q?feat:=20custom=20exception=20=EC=A0=95?= =?UTF-8?q?=EC=9D=98=20(`NoSuchElementException`)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gift/controller/NoSuchElementException.java | 15 +++++++++++++++ .../java/gift/controller/ProductController.java | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 src/main/java/gift/controller/NoSuchElementException.java diff --git a/src/main/java/gift/controller/NoSuchElementException.java b/src/main/java/gift/controller/NoSuchElementException.java new file mode 100644 index 000000000..deba494f8 --- /dev/null +++ b/src/main/java/gift/controller/NoSuchElementException.java @@ -0,0 +1,15 @@ +package gift.controller; + +public class NoSuchElementException extends RuntimeException { + + private final Long productId; + + public NoSuchElementException(Long productId) { + super("Product not found with id: " + productId); + this.productId = productId; + } + + public Long getProductId() { + return productId; + } +} diff --git a/src/main/java/gift/controller/ProductController.java b/src/main/java/gift/controller/ProductController.java index 762e2c0a7..4396f312b 100644 --- a/src/main/java/gift/controller/ProductController.java +++ b/src/main/java/gift/controller/ProductController.java @@ -35,7 +35,7 @@ public List getAllProducts() { @GetMapping("/{id}") public ProductResponseDto getProduct(@PathVariable Long id) { Product product = productRepository.findById(id) - .orElseThrow(() -> new RuntimeException("Product not found")); + .orElseThrow(() -> new NoSuchElementException(id)); return ProductResponseDto.from(product); } From 98c367e637c4d81572d29552b2ea9750c8904db8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EC=84=B1?= <166998868+castlekimdev@users.noreply.github.com> Date: Sun, 30 Jun 2024 23:32:55 +0900 Subject: [PATCH 15/20] =?UTF-8?q?chore:=20Local=20DB=20=EC=97=B0=EB=8F=99?= =?UTF-8?q?=20=EC=A0=95=EB=B3=B4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/application.properties | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 3d16b65f4..d878b7dbe 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1 +1,6 @@ spring.application.name=spring-gift +spring.h2.console.enabled=true +spring.datasource.url=jdbc:h2:mem:test +spring.sql.init.schema-locations=classpath:/static/sql/schema.sql +spring.sql.init.data-locations=classpath:/static/sql/data.sql +spring.sql.init.mode=always From 713078f9871bdcab1801624b9ca7b896cc2cb696 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EC=84=B1?= <166998868+castlekimdev@users.noreply.github.com> Date: Mon, 1 Jul 2024 12:10:31 +0900 Subject: [PATCH 16/20] =?UTF-8?q?refactor:=20util=EC=97=90=20=EC=A0=95?= =?UTF-8?q?=EC=9D=98=EB=90=9C=20`NoSuchElementException`=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=ED=95=98=EB=8F=84=EB=A1=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gift/controller/NoSuchElementException.java | 15 --------------- .../java/gift/controller/ProductController.java | 5 +++-- 2 files changed, 3 insertions(+), 17 deletions(-) delete mode 100644 src/main/java/gift/controller/NoSuchElementException.java diff --git a/src/main/java/gift/controller/NoSuchElementException.java b/src/main/java/gift/controller/NoSuchElementException.java deleted file mode 100644 index deba494f8..000000000 --- a/src/main/java/gift/controller/NoSuchElementException.java +++ /dev/null @@ -1,15 +0,0 @@ -package gift.controller; - -public class NoSuchElementException extends RuntimeException { - - private final Long productId; - - public NoSuchElementException(Long productId) { - super("Product not found with id: " + productId); - this.productId = productId; - } - - public Long getProductId() { - return productId; - } -} diff --git a/src/main/java/gift/controller/ProductController.java b/src/main/java/gift/controller/ProductController.java index 4396f312b..6c763f513 100644 --- a/src/main/java/gift/controller/ProductController.java +++ b/src/main/java/gift/controller/ProductController.java @@ -6,6 +6,7 @@ import gift.domain.Product; import gift.repository.ProductRepository; import java.util.List; +import java.util.NoSuchElementException; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -35,7 +36,7 @@ public List getAllProducts() { @GetMapping("/{id}") public ProductResponseDto getProduct(@PathVariable Long id) { Product product = productRepository.findById(id) - .orElseThrow(() -> new NoSuchElementException(id)); + .orElseThrow(() -> new NoSuchElementException("Product not found. productId: " + id)); return ProductResponseDto.from(product); } @@ -54,7 +55,7 @@ public void updateProduct( @RequestBody ProductUpdateRequestDto productUpdateRequest ) { Product originalProduct = productRepository.findById(id) - .orElseThrow(() -> new RuntimeException("Product not found")); + .orElseThrow(() -> new NoSuchElementException("Product not found. productId: " + id)); Product updatedProduct = applyUpdate(originalProduct, productUpdateRequest); productRepository.save(updatedProduct); From 9e3d9e7fc96f6e9271bb3485e2d2a7967cc8ff4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EC=84=B1?= <166998868+castlekimdev@users.noreply.github.com> Date: Mon, 1 Jul 2024 12:10:54 +0900 Subject: [PATCH 17/20] =?UTF-8?q?fix:=20`RequestMapping`=20=EC=98=AC?= =?UTF-8?q?=EB=B0=94=EB=A5=B4=EA=B2=8C=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/gift/controller/ProductController.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/gift/controller/ProductController.java b/src/main/java/gift/controller/ProductController.java index 6c763f513..9dec1971d 100644 --- a/src/main/java/gift/controller/ProductController.java +++ b/src/main/java/gift/controller/ProductController.java @@ -13,9 +13,11 @@ import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -@RestController("/products") +@RestController +@RequestMapping("/products") public class ProductController { private final ProductRepository productRepository; From c0fc53aabfd5f8039c685588a6497764ceb1f17e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EC=84=B1?= <166998868+castlekimdev@users.noreply.github.com> Date: Mon, 1 Jul 2024 12:11:33 +0900 Subject: [PATCH 18/20] =?UTF-8?q?refactor:=20=EA=B4=80=EC=8A=B5=EC=97=90?= =?UTF-8?q?=20=EB=94=B0=EB=9D=BC=20setter=20=EC=9D=B4=EB=A6=84=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gift/controller/ProductController.java | 8 +++--- .../controller/dto/ProductResponseDto.java | 4 +-- src/main/java/gift/domain/Product.java | 25 +++++-------------- .../repository/ProductRepositoryImpl.java | 8 +++--- 4 files changed, 16 insertions(+), 29 deletions(-) diff --git a/src/main/java/gift/controller/ProductController.java b/src/main/java/gift/controller/ProductController.java index 9dec1971d..dc2e2c1cb 100644 --- a/src/main/java/gift/controller/ProductController.java +++ b/src/main/java/gift/controller/ProductController.java @@ -79,20 +79,20 @@ private Product productOf(ProductCreateRequestDto productCreateRequest) { private Product applyUpdate(Product originalProduct, ProductUpdateRequestDto productUpdateRequest) { - String name = originalProduct.name(); + String name = originalProduct.getName(); if (productUpdateRequest.name() != null) { name = productUpdateRequest.name(); } - Integer price = originalProduct.price(); + Integer price = originalProduct.getPrice(); if (productUpdateRequest.price() != null) { price = productUpdateRequest.price(); } - String imageUrl = originalProduct.imageUrl(); + String imageUrl = originalProduct.getImageUrl(); if (productUpdateRequest.imageUrl() != null) { imageUrl = productUpdateRequest.imageUrl(); } - return new Product(originalProduct.id(), name, price, imageUrl); + return new Product(originalProduct.getId(), name, price, imageUrl); } } diff --git a/src/main/java/gift/controller/dto/ProductResponseDto.java b/src/main/java/gift/controller/dto/ProductResponseDto.java index 8f51d826b..6e3a1fcab 100644 --- a/src/main/java/gift/controller/dto/ProductResponseDto.java +++ b/src/main/java/gift/controller/dto/ProductResponseDto.java @@ -10,7 +10,7 @@ public record ProductResponseDto( ) { public static ProductResponseDto from(Product product) { - return new ProductResponseDto(product.id(), product.name(), product.price(), - product.imageUrl()); + return new ProductResponseDto(product.getId(), product.getName(), product.getPrice(), + product.getImageUrl()); } } diff --git a/src/main/java/gift/domain/Product.java b/src/main/java/gift/domain/Product.java index e1cb95473..af2f04bba 100644 --- a/src/main/java/gift/domain/Product.java +++ b/src/main/java/gift/domain/Product.java @@ -4,7 +4,7 @@ public class Product { - private Long id; + private final Long id; private String name; private Integer price; private String imageUrl; @@ -16,37 +16,24 @@ public Product(Long id, String name, Integer price, String imageUrl) { this.imageUrl = imageUrl; } - public Long id() { - return id; - } - public void setId(Long id) { - this.id = id; + public Long getId() { + return id; } - public String name() { + public String getName() { return name; } - public void setName(String name) { - this.name = name; - } - - public Integer price() { + public Integer getPrice() { return price; } - public void setPrice(Integer price) { - this.price = price; - } - public String imageUrl() { + public String getImageUrl() { return imageUrl; } - public void setImageUrl(String imageUrl) { - this.imageUrl = imageUrl; - } @Override public String toString() { diff --git a/src/main/java/gift/repository/ProductRepositoryImpl.java b/src/main/java/gift/repository/ProductRepositoryImpl.java index 6a8304422..17236ad59 100644 --- a/src/main/java/gift/repository/ProductRepositoryImpl.java +++ b/src/main/java/gift/repository/ProductRepositoryImpl.java @@ -45,14 +45,14 @@ public boolean exists(Long id) { @Override public void save(Product product) { - if (exists(product.id())) { + if (exists(product.getId())) { String sql = "UPDATE `products` SET `name` = ?, `price` = ?, `image_url` = ? WHERE `id` = ?"; - jdbcTemplate.update(sql, product.name(), product.price(), product.imageUrl(), - product.id()); + jdbcTemplate.update(sql, product.getName(), product.getPrice(), product.getImageUrl(), + product.getId()); return; } String sql = "INSERT INTO `products` (`name`, `price`, `image_url`) VALUES (?, ?, ?)"; - jdbcTemplate.update(sql, product.name(), product.price(), product.imageUrl()); + jdbcTemplate.update(sql, product.getName(), product.getPrice(), product.getImageUrl()); } @Override From 83c8325299e5dd7fa8aa3d735d586c1d9268c6a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EC=84=B1?= <166998868+castlekimdev@users.noreply.github.com> Date: Mon, 1 Jul 2024 12:14:34 +0900 Subject: [PATCH 19/20] =?UTF-8?q?refactor:=20controller=EA=B0=80=20domain?= =?UTF-8?q?=20service=EC=97=90=20=EC=9D=98=EC=A1=B4=ED=95=98=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gift/controller/ProductController.java | 70 +++------------ .../java/gift/service/ProductService.java | 86 +++++++++++++++++++ 2 files changed, 98 insertions(+), 58 deletions(-) create mode 100644 src/main/java/gift/service/ProductService.java diff --git a/src/main/java/gift/controller/ProductController.java b/src/main/java/gift/controller/ProductController.java index dc2e2c1cb..e0476c25f 100644 --- a/src/main/java/gift/controller/ProductController.java +++ b/src/main/java/gift/controller/ProductController.java @@ -3,10 +3,8 @@ import gift.controller.dto.ProductCreateRequestDto; import gift.controller.dto.ProductResponseDto; import gift.controller.dto.ProductUpdateRequestDto; -import gift.domain.Product; -import gift.repository.ProductRepository; +import gift.service.ProductService; import java.util.List; -import java.util.NoSuchElementException; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -20,79 +18,35 @@ @RequestMapping("/products") public class ProductController { - private final ProductRepository productRepository; + private final ProductService productService; - public ProductController(ProductRepository productRepository) { - this.productRepository = productRepository; + public ProductController(ProductService productService) { + this.productService = productService; } @GetMapping public List getAllProducts() { - return productRepository - .findAll() - .stream() - .map(ProductResponseDto::from) - .toList(); + return productService.getAllProducts(); } @GetMapping("/{id}") public ProductResponseDto getProduct(@PathVariable Long id) { - Product product = productRepository.findById(id) - .orElseThrow(() -> new NoSuchElementException("Product not found. productId: " + id)); - return ProductResponseDto.from(product); + return productService.getProduct(id); } - @PostMapping - public void addProduct( - @RequestBody ProductCreateRequestDto productCreateRequest - ) { - Product product = productOf(productCreateRequest); - productRepository.save(product); + public void addProduct(@RequestBody ProductCreateRequestDto productCreateRequest) { + productService.addProduct(productCreateRequest); } @PutMapping("/{id}") - public void updateProduct( - @PathVariable Long id, - @RequestBody ProductUpdateRequestDto productUpdateRequest - ) { - Product originalProduct = productRepository.findById(id) - .orElseThrow(() -> new NoSuchElementException("Product not found. productId: " + id)); - - Product updatedProduct = applyUpdate(originalProduct, productUpdateRequest); - productRepository.save(updatedProduct); + public void updateProduct(@PathVariable Long id, + @RequestBody ProductUpdateRequestDto productUpdateRequest) { + productService.updateProduct(id, productUpdateRequest); } @DeleteMapping("/{id}") public void deleteProduct(@PathVariable Long id) { - productRepository.remove(id); - } - - private Product productOf(ProductCreateRequestDto productCreateRequest) { - return new Product( - 0L, - productCreateRequest.name(), - productCreateRequest.price(), - productCreateRequest.imageUrl() - ); - } - - private Product applyUpdate(Product originalProduct, - ProductUpdateRequestDto productUpdateRequest) { - String name = originalProduct.getName(); - if (productUpdateRequest.name() != null) { - name = productUpdateRequest.name(); - } - - Integer price = originalProduct.getPrice(); - if (productUpdateRequest.price() != null) { - price = productUpdateRequest.price(); - } - - String imageUrl = originalProduct.getImageUrl(); - if (productUpdateRequest.imageUrl() != null) { - imageUrl = productUpdateRequest.imageUrl(); - } - return new Product(originalProduct.getId(), name, price, imageUrl); + productService.deleteProduct(id); } } diff --git a/src/main/java/gift/service/ProductService.java b/src/main/java/gift/service/ProductService.java new file mode 100644 index 000000000..760ce241d --- /dev/null +++ b/src/main/java/gift/service/ProductService.java @@ -0,0 +1,86 @@ +package gift.service; + +import gift.controller.dto.ProductCreateRequestDto; +import gift.controller.dto.ProductResponseDto; +import gift.controller.dto.ProductUpdateRequestDto; +import gift.domain.Product; +import gift.repository.ProductRepository; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.stream.Collectors; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class ProductService { + + private final ProductRepository productRepository; + + public ProductService(ProductRepository productRepository) { + this.productRepository = productRepository; + } + + @Transactional(readOnly = true) + public List getAllProducts() { + return productRepository + .findAll() + .stream() + .map(ProductResponseDto::from) + .collect(Collectors.toList()); + } + + @Transactional(readOnly = true) + public ProductResponseDto getProduct(Long id) { + Product product = productRepository.findById(id) + .orElseThrow(() -> new NoSuchElementException("Product not found. productId: " + id)); + return ProductResponseDto.from(product); + } + + @Transactional + public void addProduct(ProductCreateRequestDto productCreateRequest) { + Product product = productOf(productCreateRequest); + productRepository.save(product); + } + + @Transactional + public void updateProduct(Long id, ProductUpdateRequestDto productUpdateRequest) { + Product originalProduct = productRepository.findById(id) + .orElseThrow(() -> new NoSuchElementException("Product not found. productId: " + id)); + + Product updatedProduct = applyUpdate(originalProduct, productUpdateRequest); + productRepository.save(updatedProduct); + } + + @Transactional + public void deleteProduct(Long id) { + productRepository.remove(id); + } + + private Product productOf(ProductCreateRequestDto productCreateRequest) { + return new Product( + 0L, + productCreateRequest.name(), + productCreateRequest.price(), + productCreateRequest.imageUrl() + ); + } + + private Product applyUpdate(Product originalProduct, + ProductUpdateRequestDto productUpdateRequest) { + String name = originalProduct.getName(); + if (productUpdateRequest.name() != null) { + name = productUpdateRequest.name(); + } + + Integer price = originalProduct.getPrice(); + if (productUpdateRequest.price() != null) { + price = productUpdateRequest.price(); + } + + String imageUrl = originalProduct.getImageUrl(); + if (productUpdateRequest.imageUrl() != null) { + imageUrl = productUpdateRequest.imageUrl(); + } + return new Product(originalProduct.getId(), name, price, imageUrl); + } +} From 5ebd921eefcc508726560c2ef5a67dd60aa4ef12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EC=84=B1?= <166998868+castlekimdev@users.noreply.github.com> Date: Mon, 1 Jul 2024 12:19:34 +0900 Subject: [PATCH 20/20] =?UTF-8?q?chore:=20data.sql,=20schema.sql=20?= =?UTF-8?q?=EC=98=AC=EB=B0=94=EB=A5=B8=20=EC=9C=84=EC=B9=98=EB=A1=9C=20?= =?UTF-8?q?=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/static/sql/data.sql | 200 ++++++++++++++++++ .../static/{schma.sql => sql/schema.sql} | 0 2 files changed, 200 insertions(+) create mode 100644 src/main/resources/static/sql/data.sql rename src/main/resources/static/{schma.sql => sql/schema.sql} (100%) diff --git a/src/main/resources/static/sql/data.sql b/src/main/resources/static/sql/data.sql new file mode 100644 index 000000000..a04a423cb --- /dev/null +++ b/src/main/resources/static/sql/data.sql @@ -0,0 +1,200 @@ +insert into products (name, price, image_url) +values ('Jarred', 4750, 'http://dummyimage.com/165x100.png/dddddd/000000'); +insert into products (name, price, image_url) +values ('Kearney', 548, 'http://dummyimage.com/106x100.png/dddddd/000000'); +insert into products (name, price, image_url) +values ('Evan', 83663, 'http://dummyimage.com/188x100.png/ff4444/ffffff'); +insert into products (name, price, image_url) +values ('Shae', 54900, 'http://dummyimage.com/182x100.png/ff4444/ffffff'); +insert into products (name, price, image_url) +values ('Merrill', 78201, 'http://dummyimage.com/163x100.png/dddddd/000000'); +insert into products (name, price, image_url) +values ('Rozina', 55280, 'http://dummyimage.com/123x100.png/dddddd/000000'); +insert into products (name, price, image_url) +values ('Devin', 98380, 'http://dummyimage.com/101x100.png/cc0000/ffffff'); +insert into products (name, price, image_url) +values ('Reece', 87688, 'http://dummyimage.com/125x100.png/cc0000/ffffff'); +insert into products (name, price, image_url) +values ('Findlay', 61291, 'http://dummyimage.com/225x100.png/ff4444/ffffff'); +insert into products (name, price, image_url) +values ('Samuele', 61006, 'http://dummyimage.com/125x100.png/dddddd/000000'); +insert into products (name, price, image_url) +values ('Nobie', 33492, 'http://dummyimage.com/208x100.png/dddddd/000000'); +insert into products (name, price, image_url) +values ('Jacob', 16626, 'http://dummyimage.com/176x100.png/5fa2dd/ffffff'); +insert into products (name, price, image_url) +values ('Babb', 34480, 'http://dummyimage.com/198x100.png/5fa2dd/ffffff'); +insert into products (name, price, image_url) +values ('Tarra', 24837, 'http://dummyimage.com/216x100.png/5fa2dd/ffffff'); +insert into products (name, price, image_url) +values ('Paulie', 18980, 'http://dummyimage.com/178x100.png/dddddd/000000'); +insert into products (name, price, image_url) +values ('Pascale', 10113, 'http://dummyimage.com/145x100.png/dddddd/000000'); +insert into products (name, price, image_url) +values ('Michel', 86388, 'http://dummyimage.com/212x100.png/ff4444/ffffff'); +insert into products (name, price, image_url) +values ('Clive', 7423, 'http://dummyimage.com/171x100.png/5fa2dd/ffffff'); +insert into products (name, price, image_url) +values ('Merle', 6880, 'http://dummyimage.com/177x100.png/dddddd/000000'); +insert into products (name, price, image_url) +values ('Lindy', 86008, 'http://dummyimage.com/192x100.png/cc0000/ffffff'); +insert into products (name, price, image_url) +values ('Edd', 5194, 'http://dummyimage.com/189x100.png/5fa2dd/ffffff'); +insert into products (name, price, image_url) +values ('Lindsey', 45508, 'http://dummyimage.com/229x100.png/dddddd/000000'); +insert into products (name, price, image_url) +values ('Joachim', 92509, 'http://dummyimage.com/199x100.png/5fa2dd/ffffff'); +insert into products (name, price, image_url) +values ('Filberte', 84801, 'http://dummyimage.com/236x100.png/ff4444/ffffff'); +insert into products (name, price, image_url) +values ('Granny', 95976, 'http://dummyimage.com/169x100.png/ff4444/ffffff'); +insert into products (name, price, image_url) +values ('Tiebout', 35045, 'http://dummyimage.com/182x100.png/dddddd/000000'); +insert into products (name, price, image_url) +values ('Miltie', 19555, 'http://dummyimage.com/191x100.png/cc0000/ffffff'); +insert into products (name, price, image_url) +values ('Estrella', 82325, 'http://dummyimage.com/198x100.png/5fa2dd/ffffff'); +insert into products (name, price, image_url) +values ('Hube', 47709, 'http://dummyimage.com/206x100.png/dddddd/000000'); +insert into products (name, price, image_url) +values ('Abba', 10819, 'http://dummyimage.com/138x100.png/5fa2dd/ffffff'); +insert into products (name, price, image_url) +values ('Meaghan', 46674, 'http://dummyimage.com/226x100.png/dddddd/000000'); +insert into products (name, price, image_url) +values ('Hortense', 31061, 'http://dummyimage.com/183x100.png/ff4444/ffffff'); +insert into products (name, price, image_url) +values ('Orran', 41196, 'http://dummyimage.com/192x100.png/ff4444/ffffff'); +insert into products (name, price, image_url) +values ('Lannie', 66318, 'http://dummyimage.com/117x100.png/dddddd/000000'); +insert into products (name, price, image_url) +values ('Wadsworth', 85268, 'http://dummyimage.com/205x100.png/cc0000/ffffff'); +insert into products (name, price, image_url) +values ('Rafaelia', 51277, 'http://dummyimage.com/218x100.png/5fa2dd/ffffff'); +insert into products (name, price, image_url) +values ('Jerrie', 52659, 'http://dummyimage.com/155x100.png/cc0000/ffffff'); +insert into products (name, price, image_url) +values ('Symon', 29156, 'http://dummyimage.com/172x100.png/dddddd/000000'); +insert into products (name, price, image_url) +values ('Trish', 7859, 'http://dummyimage.com/165x100.png/cc0000/ffffff'); +insert into products (name, price, image_url) +values ('Jule', 13644, 'http://dummyimage.com/237x100.png/cc0000/ffffff'); +insert into products (name, price, image_url) +values ('Joly', 87015, 'http://dummyimage.com/132x100.png/ff4444/ffffff'); +insert into products (name, price, image_url) +values ('Gracia', 94879, 'http://dummyimage.com/133x100.png/5fa2dd/ffffff'); +insert into products (name, price, image_url) +values ('Nicko', 10097, 'http://dummyimage.com/150x100.png/5fa2dd/ffffff'); +insert into products (name, price, image_url) +values ('Barrie', 1743, 'http://dummyimage.com/205x100.png/ff4444/ffffff'); +insert into products (name, price, image_url) +values ('Perceval', 29793, 'http://dummyimage.com/118x100.png/ff4444/ffffff'); +insert into products (name, price, image_url) +values ('Adey', 36524, 'http://dummyimage.com/188x100.png/5fa2dd/ffffff'); +insert into products (name, price, image_url) +values ('Cleve', 53941, 'http://dummyimage.com/179x100.png/dddddd/000000'); +insert into products (name, price, image_url) +values ('Padget', 39582, 'http://dummyimage.com/249x100.png/cc0000/ffffff'); +insert into products (name, price, image_url) +values ('Rupert', 72787, 'http://dummyimage.com/138x100.png/ff4444/ffffff'); +insert into products (name, price, image_url) +values ('Claudelle', 82004, 'http://dummyimage.com/206x100.png/5fa2dd/ffffff'); +insert into products (name, price, image_url) +values ('Marlon', 34296, 'http://dummyimage.com/161x100.png/cc0000/ffffff'); +insert into products (name, price, image_url) +values ('Jeremy', 55345, 'http://dummyimage.com/205x100.png/5fa2dd/ffffff'); +insert into products (name, price, image_url) +values ('Sanders', 23124, 'http://dummyimage.com/106x100.png/ff4444/ffffff'); +insert into products (name, price, image_url) +values ('Jordain', 96017, 'http://dummyimage.com/164x100.png/dddddd/000000'); +insert into products (name, price, image_url) +values ('Larina', 46169, 'http://dummyimage.com/234x100.png/dddddd/000000'); +insert into products (name, price, image_url) +values ('Carlota', 72232, 'http://dummyimage.com/189x100.png/ff4444/ffffff'); +insert into products (name, price, image_url) +values ('Paco', 26742, 'http://dummyimage.com/121x100.png/5fa2dd/ffffff'); +insert into products (name, price, image_url) +values ('Udall', 78229, 'http://dummyimage.com/124x100.png/cc0000/ffffff'); +insert into products (name, price, image_url) +values ('Mirella', 44104, 'http://dummyimage.com/179x100.png/ff4444/ffffff'); +insert into products (name, price, image_url) +values ('Buiron', 2447, 'http://dummyimage.com/233x100.png/cc0000/ffffff'); +insert into products (name, price, image_url) +values ('Kevin', 53876, 'http://dummyimage.com/153x100.png/cc0000/ffffff'); +insert into products (name, price, image_url) +values ('Thea', 82590, 'http://dummyimage.com/158x100.png/cc0000/ffffff'); +insert into products (name, price, image_url) +values ('Esme', 30216, 'http://dummyimage.com/197x100.png/dddddd/000000'); +insert into products (name, price, image_url) +values ('Pen', 3677, 'http://dummyimage.com/232x100.png/dddddd/000000'); +insert into products (name, price, image_url) +values ('Tedda', 98656, 'http://dummyimage.com/191x100.png/cc0000/ffffff'); +insert into products (name, price, image_url) +values ('Milli', 30932, 'http://dummyimage.com/156x100.png/5fa2dd/ffffff'); +insert into products (name, price, image_url) +values ('Judie', 68398, 'http://dummyimage.com/237x100.png/5fa2dd/ffffff'); +insert into products (name, price, image_url) +values ('Marline', 61978, 'http://dummyimage.com/124x100.png/ff4444/ffffff'); +insert into products (name, price, image_url) +values ('Marleah', 48428, 'http://dummyimage.com/220x100.png/cc0000/ffffff'); +insert into products (name, price, image_url) +values ('Kristoffer', 61680, 'http://dummyimage.com/184x100.png/ff4444/ffffff'); +insert into products (name, price, image_url) +values ('Carolynn', 45576, 'http://dummyimage.com/223x100.png/cc0000/ffffff'); +insert into products (name, price, image_url) +values ('Winne', 76689, 'http://dummyimage.com/183x100.png/cc0000/ffffff'); +insert into products (name, price, image_url) +values ('Arabelle', 50478, 'http://dummyimage.com/241x100.png/dddddd/000000'); +insert into products (name, price, image_url) +values ('Jerrilee', 49320, 'http://dummyimage.com/104x100.png/cc0000/ffffff'); +insert into products (name, price, image_url) +values ('Baron', 96069, 'http://dummyimage.com/191x100.png/dddddd/000000'); +insert into products (name, price, image_url) +values ('Etti', 47457, 'http://dummyimage.com/248x100.png/5fa2dd/ffffff'); +insert into products (name, price, image_url) +values ('Nicolai', 30183, 'http://dummyimage.com/192x100.png/cc0000/ffffff'); +insert into products (name, price, image_url) +values ('Dari', 78081, 'http://dummyimage.com/248x100.png/ff4444/ffffff'); +insert into products (name, price, image_url) +values ('Quintin', 38278, 'http://dummyimage.com/201x100.png/ff4444/ffffff'); +insert into products (name, price, image_url) +values ('Barnard', 5511, 'http://dummyimage.com/102x100.png/ff4444/ffffff'); +insert into products (name, price, image_url) +values ('Jamal', 80626, 'http://dummyimage.com/184x100.png/ff4444/ffffff'); +insert into products (name, price, image_url) +values ('Davin', 95671, 'http://dummyimage.com/200x100.png/5fa2dd/ffffff'); +insert into products (name, price, image_url) +values ('Julina', 95650, 'http://dummyimage.com/133x100.png/cc0000/ffffff'); +insert into products (name, price, image_url) +values ('Ripley', 30952, 'http://dummyimage.com/172x100.png/cc0000/ffffff'); +insert into products (name, price, image_url) +values ('Hamnet', 80710, 'http://dummyimage.com/233x100.png/5fa2dd/ffffff'); +insert into products (name, price, image_url) +values ('Haleigh', 19799, 'http://dummyimage.com/102x100.png/ff4444/ffffff'); +insert into products (name, price, image_url) +values ('Meg', 21167, 'http://dummyimage.com/167x100.png/dddddd/000000'); +insert into products (name, price, image_url) +values ('Wally', 78167, 'http://dummyimage.com/243x100.png/5fa2dd/ffffff'); +insert into products (name, price, image_url) +values ('Lannie', 78335, 'http://dummyimage.com/114x100.png/cc0000/ffffff'); +insert into products (name, price, image_url) +values ('Beverley', 43686, 'http://dummyimage.com/154x100.png/ff4444/ffffff'); +insert into products (name, price, image_url) +values ('Keefe', 70268, 'http://dummyimage.com/126x100.png/dddddd/000000'); +insert into products (name, price, image_url) +values ('Renae', 50565, 'http://dummyimage.com/214x100.png/5fa2dd/ffffff'); +insert into products (name, price, image_url) +values ('Margie', 47698, 'http://dummyimage.com/177x100.png/ff4444/ffffff'); +insert into products (name, price, image_url) +values ('Elisabetta', 16919, 'http://dummyimage.com/168x100.png/5fa2dd/ffffff'); +insert into products (name, price, image_url) +values ('Nickola', 38068, 'http://dummyimage.com/183x100.png/cc0000/ffffff'); +insert into products (name, price, image_url) +values ('Hunfredo', 45432, 'http://dummyimage.com/220x100.png/5fa2dd/ffffff'); +insert into products (name, price, image_url) +values ('Jyoti', 99675, 'http://dummyimage.com/159x100.png/ff4444/ffffff'); +insert into products (name, price, image_url) +values ('Garland', 92936, 'http://dummyimage.com/120x100.png/ff4444/ffffff'); +insert into products (name, price, image_url) +values ('Anthony', 33928, 'http://dummyimage.com/170x100.png/cc0000/ffffff'); +insert into products (name, price, image_url) +values ('Ada', 7528, 'http://dummyimage.com/164x100.png/5fa2dd/ffffff'); diff --git a/src/main/resources/static/schma.sql b/src/main/resources/static/sql/schema.sql similarity index 100% rename from src/main/resources/static/schma.sql rename to src/main/resources/static/sql/schema.sql