diff --git a/pom.xml b/pom.xml
index cf704585..039a4d31 100644
--- a/pom.xml
+++ b/pom.xml
@@ -30,6 +30,33 @@
org.springframework.boot
spring-boot-autoconfigure
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-devtools
+ runtime
+ true
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+ com.h2database
+ h2
+
+
+ mysql
+ mysql-connector-java
+
+
+ org.projectlombok
+ lombok
+
diff --git a/src/main/java/mate/academy/springboot/datajpa/controller/CategoryController.java b/src/main/java/mate/academy/springboot/datajpa/controller/CategoryController.java
new file mode 100644
index 00000000..b2e48905
--- /dev/null
+++ b/src/main/java/mate/academy/springboot/datajpa/controller/CategoryController.java
@@ -0,0 +1,49 @@
+package mate.academy.springboot.datajpa.controller;
+
+import lombok.RequiredArgsConstructor;
+import mate.academy.springboot.datajpa.dto.CategoryRequestDto;
+import mate.academy.springboot.datajpa.dto.CategoryResponseDto;
+import mate.academy.springboot.datajpa.dto.mapper.DtoMapper;
+import mate.academy.springboot.datajpa.model.Category;
+import mate.academy.springboot.datajpa.service.CategoryService;
+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.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("/categories")
+@RequiredArgsConstructor
+public class CategoryController {
+ private final CategoryService categoryService;
+ private final DtoMapper categoryMapper;
+
+ @PostMapping
+ public CategoryResponseDto create(@RequestBody CategoryRequestDto requestDto) {
+ Category category = categoryService.create(categoryMapper.mapToModel(requestDto));
+ return categoryMapper.mapToDto(category);
+ }
+
+ @GetMapping("{id}")
+ public CategoryResponseDto getById(@PathVariable Long id) {
+ Category category = categoryService.getById(id);
+ return categoryMapper.mapToDto(category);
+ }
+
+ @DeleteMapping("{id}")
+ public void delete(@PathVariable Long id) {
+ categoryService.delete(id);
+ }
+
+ @PutMapping("/{id}")
+ public CategoryResponseDto update(@PathVariable Long id,
+ @RequestBody CategoryRequestDto requestDto) {
+ Category category = categoryMapper.mapToModel(requestDto);
+ category.setId(id);
+ return categoryMapper.mapToDto(categoryService.create(category));
+ }
+}
diff --git a/src/main/java/mate/academy/springboot/datajpa/controller/InjectController.java b/src/main/java/mate/academy/springboot/datajpa/controller/InjectController.java
new file mode 100644
index 00000000..6bcde5cf
--- /dev/null
+++ b/src/main/java/mate/academy/springboot/datajpa/controller/InjectController.java
@@ -0,0 +1,48 @@
+package mate.academy.springboot.datajpa.controller;
+
+import java.math.BigDecimal;
+import lombok.AllArgsConstructor;
+import mate.academy.springboot.datajpa.model.Category;
+import mate.academy.springboot.datajpa.model.Product;
+import mate.academy.springboot.datajpa.service.CategoryService;
+import mate.academy.springboot.datajpa.service.ProductService;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@AllArgsConstructor
+@RestController
+@RequestMapping("/inject")
+public class InjectController {
+ private final ProductService productService;
+ private final CategoryService categoryService;
+
+ @GetMapping
+ public String injectData() {
+ Category phones = new Category();
+ phones.setName("Phones");
+ categoryService.create(phones);
+ Category macBook = new Category();
+ macBook.setName("Laptop");
+ categoryService.create(macBook);
+
+ Product iphoneX = new Product();
+ iphoneX.setTitle("Iphone X");
+ iphoneX.setPrice(BigDecimal.valueOf(999));
+ iphoneX.setCategory(phones);
+ productService.create(iphoneX);
+
+ Product iphone12 = new Product();
+ iphone12.setTitle("Iphone 12");
+ iphone12.setPrice(BigDecimal.valueOf(1299));
+ iphone12.setCategory(phones);
+ productService.create(iphone12);
+
+ Product airMax = new Product();
+ airMax.setTitle("MacBook Air");
+ airMax.setPrice(BigDecimal.valueOf(2100));
+ airMax.setCategory(macBook);
+ productService.create(airMax);
+ return "Done";
+ }
+}
diff --git a/src/main/java/mate/academy/springboot/datajpa/controller/ProductController.java b/src/main/java/mate/academy/springboot/datajpa/controller/ProductController.java
new file mode 100644
index 00000000..37f8bc36
--- /dev/null
+++ b/src/main/java/mate/academy/springboot/datajpa/controller/ProductController.java
@@ -0,0 +1,70 @@
+package mate.academy.springboot.datajpa.controller;
+
+import java.math.BigDecimal;
+import java.util.List;
+import java.util.stream.Collectors;
+import lombok.AllArgsConstructor;
+import mate.academy.springboot.datajpa.dto.ProductRequestDto;
+import mate.academy.springboot.datajpa.dto.ProductResponseDto;
+import mate.academy.springboot.datajpa.dto.mapper.DtoMapper;
+import mate.academy.springboot.datajpa.model.Product;
+import mate.academy.springboot.datajpa.service.ProductService;
+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.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+@AllArgsConstructor
+@RestController
+@RequestMapping("/products")
+public class ProductController {
+ private final ProductService productService;
+ private final DtoMapper productMapper;
+
+ @PostMapping
+ public ProductResponseDto create(@RequestBody ProductRequestDto productRequestDto) {
+ Product product = productService.create(productMapper.mapToModel(productRequestDto));
+ return productMapper.mapToDto(product);
+ }
+
+ @GetMapping("/{id}")
+ public ProductResponseDto getById(@PathVariable Long id) {
+ return productMapper.mapToDto(productService.getById(id));
+ }
+
+ @DeleteMapping("/{id}")
+ public void delete(@PathVariable Long id) {
+ productService.delete(id);
+ }
+
+ @PutMapping("/{id}")
+ public ProductResponseDto update(@PathVariable Long id,
+ @RequestBody ProductRequestDto productRequestDto) {
+ Product product = productMapper.mapToModel(productRequestDto);
+ product.setId(id);
+ productService.update(product);
+ return productMapper.mapToDto(product);
+ }
+
+ @GetMapping("/price-between")
+ public List findAllByPriceBetween(@RequestParam BigDecimal from,
+ @RequestParam BigDecimal to) {
+ return productService.findAllByPriceBetween(from, to)
+ .stream()
+ .map(productMapper::mapToDto)
+ .collect(Collectors.toList());
+ }
+
+ @GetMapping("/by-category")
+ public List findAllByCategoryIn(@RequestParam List categories) {
+ return productService.findAllByCategoryNameIn(categories)
+ .stream()
+ .map(productMapper::mapToDto)
+ .collect(Collectors.toList());
+ }
+}
diff --git a/src/main/java/mate/academy/springboot/datajpa/dto/CategoryRequestDto.java b/src/main/java/mate/academy/springboot/datajpa/dto/CategoryRequestDto.java
new file mode 100644
index 00000000..7a0c33a5
--- /dev/null
+++ b/src/main/java/mate/academy/springboot/datajpa/dto/CategoryRequestDto.java
@@ -0,0 +1,8 @@
+package mate.academy.springboot.datajpa.dto;
+
+import lombok.Data;
+
+@Data
+public class CategoryRequestDto {
+ private String name;
+}
diff --git a/src/main/java/mate/academy/springboot/datajpa/dto/CategoryResponseDto.java b/src/main/java/mate/academy/springboot/datajpa/dto/CategoryResponseDto.java
new file mode 100644
index 00000000..4c817782
--- /dev/null
+++ b/src/main/java/mate/academy/springboot/datajpa/dto/CategoryResponseDto.java
@@ -0,0 +1,9 @@
+package mate.academy.springboot.datajpa.dto;
+
+import lombok.Data;
+
+@Data
+public class CategoryResponseDto {
+ private Long id;
+ private String name;
+}
diff --git a/src/main/java/mate/academy/springboot/datajpa/dto/ProductRequestDto.java b/src/main/java/mate/academy/springboot/datajpa/dto/ProductRequestDto.java
new file mode 100644
index 00000000..2df315f9
--- /dev/null
+++ b/src/main/java/mate/academy/springboot/datajpa/dto/ProductRequestDto.java
@@ -0,0 +1,11 @@
+package mate.academy.springboot.datajpa.dto;
+
+import java.math.BigDecimal;
+import lombok.Data;
+
+@Data
+public class ProductRequestDto {
+ private String title;
+ private BigDecimal price;
+ private Long categoryId;
+}
diff --git a/src/main/java/mate/academy/springboot/datajpa/dto/ProductResponseDto.java b/src/main/java/mate/academy/springboot/datajpa/dto/ProductResponseDto.java
new file mode 100644
index 00000000..cd71254e
--- /dev/null
+++ b/src/main/java/mate/academy/springboot/datajpa/dto/ProductResponseDto.java
@@ -0,0 +1,12 @@
+package mate.academy.springboot.datajpa.dto;
+
+import java.math.BigDecimal;
+import lombok.Data;
+
+@Data
+public class ProductResponseDto {
+ private Long id;
+ private String title;
+ private BigDecimal price;
+ private Long categoryId;
+}
diff --git a/src/main/java/mate/academy/springboot/datajpa/dto/mapper/CategoryMapper.java b/src/main/java/mate/academy/springboot/datajpa/dto/mapper/CategoryMapper.java
new file mode 100644
index 00000000..31150a2e
--- /dev/null
+++ b/src/main/java/mate/academy/springboot/datajpa/dto/mapper/CategoryMapper.java
@@ -0,0 +1,26 @@
+package mate.academy.springboot.datajpa.dto.mapper;
+
+import mate.academy.springboot.datajpa.dto.CategoryRequestDto;
+import mate.academy.springboot.datajpa.dto.CategoryResponseDto;
+import mate.academy.springboot.datajpa.model.Category;
+import org.springframework.stereotype.Component;
+
+@Component
+public class CategoryMapper implements
+ DtoMapper {
+
+ @Override
+ public Category mapToModel(CategoryRequestDto dto) {
+ Category category = new Category();
+ category.setName(dto.getName());
+ return category;
+ }
+
+ @Override
+ public CategoryResponseDto mapToDto(Category category) {
+ CategoryResponseDto categoryResponseDto = new CategoryResponseDto();
+ categoryResponseDto.setId(category.getId());
+ categoryResponseDto.setName(category.getName());
+ return categoryResponseDto;
+ }
+}
diff --git a/src/main/java/mate/academy/springboot/datajpa/dto/mapper/DtoMapper.java b/src/main/java/mate/academy/springboot/datajpa/dto/mapper/DtoMapper.java
new file mode 100644
index 00000000..5172263f
--- /dev/null
+++ b/src/main/java/mate/academy/springboot/datajpa/dto/mapper/DtoMapper.java
@@ -0,0 +1,7 @@
+package mate.academy.springboot.datajpa.dto.mapper;
+
+public interface DtoMapper {
+ D mapToDto(M model);
+
+ M mapToModel(R dto);
+}
diff --git a/src/main/java/mate/academy/springboot/datajpa/dto/mapper/ProductMapper.java b/src/main/java/mate/academy/springboot/datajpa/dto/mapper/ProductMapper.java
new file mode 100644
index 00000000..89cc124b
--- /dev/null
+++ b/src/main/java/mate/academy/springboot/datajpa/dto/mapper/ProductMapper.java
@@ -0,0 +1,35 @@
+package mate.academy.springboot.datajpa.dto.mapper;
+
+import mate.academy.springboot.datajpa.dto.ProductRequestDto;
+import mate.academy.springboot.datajpa.dto.ProductResponseDto;
+import mate.academy.springboot.datajpa.model.Product;
+import mate.academy.springboot.datajpa.service.CategoryService;
+import org.springframework.stereotype.Component;
+
+@Component
+public class ProductMapper implements DtoMapper {
+ private final CategoryService categoryService;
+
+ public ProductMapper(CategoryService categoryService) {
+ this.categoryService = categoryService;
+ }
+
+ @Override
+ public Product mapToModel(ProductRequestDto dto) {
+ Product product = new Product();
+ product.setTitle(dto.getTitle());
+ product.setPrice(dto.getPrice());
+ product.setCategory(categoryService.getById(dto.getCategoryId()));
+ return product;
+ }
+
+ @Override
+ public ProductResponseDto mapToDto(Product product) {
+ ProductResponseDto productResponseDto = new ProductResponseDto();
+ productResponseDto.setId(product.getId());
+ productResponseDto.setTitle(product.getTitle());
+ productResponseDto.setPrice(product.getPrice());
+ productResponseDto.setCategoryId(product.getCategory().getId());
+ return productResponseDto;
+ }
+}
diff --git a/src/main/java/mate/academy/springboot/datajpa/model/Category.java b/src/main/java/mate/academy/springboot/datajpa/model/Category.java
new file mode 100644
index 00000000..98f76c97
--- /dev/null
+++ b/src/main/java/mate/academy/springboot/datajpa/model/Category.java
@@ -0,0 +1,16 @@
+package mate.academy.springboot.datajpa.model;
+
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import lombok.Data;
+
+@Data
+@Entity
+public class Category {
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
+ private String name;
+}
diff --git a/src/main/java/mate/academy/springboot/datajpa/model/Product.java b/src/main/java/mate/academy/springboot/datajpa/model/Product.java
new file mode 100644
index 00000000..8b6eaa09
--- /dev/null
+++ b/src/main/java/mate/academy/springboot/datajpa/model/Product.java
@@ -0,0 +1,25 @@
+package mate.academy.springboot.datajpa.model;
+
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.ManyToOne;
+import jakarta.persistence.Table;
+import java.math.BigDecimal;
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+@Entity
+@Table(name = "products")
+public class Product {
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
+ private String title;
+ private BigDecimal price;
+ @ManyToOne
+ private Category category;
+}
diff --git a/src/main/java/mate/academy/springboot/datajpa/repository/CategoryRepository.java b/src/main/java/mate/academy/springboot/datajpa/repository/CategoryRepository.java
new file mode 100644
index 00000000..ed06bf2b
--- /dev/null
+++ b/src/main/java/mate/academy/springboot/datajpa/repository/CategoryRepository.java
@@ -0,0 +1,9 @@
+package mate.academy.springboot.datajpa.repository;
+
+import mate.academy.springboot.datajpa.model.Category;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface CategoryRepository extends JpaRepository {
+}
diff --git a/src/main/java/mate/academy/springboot/datajpa/repository/ProductRepository.java b/src/main/java/mate/academy/springboot/datajpa/repository/ProductRepository.java
new file mode 100644
index 00000000..b7827b87
--- /dev/null
+++ b/src/main/java/mate/academy/springboot/datajpa/repository/ProductRepository.java
@@ -0,0 +1,14 @@
+package mate.academy.springboot.datajpa.repository;
+
+import java.math.BigDecimal;
+import java.util.List;
+import mate.academy.springboot.datajpa.model.Product;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface ProductRepository extends JpaRepository {
+ List findAllByPriceBetween(BigDecimal from, BigDecimal to);
+
+ List findAllByCategoryNameIn(List categories);
+}
diff --git a/src/main/java/mate/academy/springboot/datajpa/service/CategoryService.java b/src/main/java/mate/academy/springboot/datajpa/service/CategoryService.java
new file mode 100644
index 00000000..d1ba2b56
--- /dev/null
+++ b/src/main/java/mate/academy/springboot/datajpa/service/CategoryService.java
@@ -0,0 +1,13 @@
+package mate.academy.springboot.datajpa.service;
+
+import mate.academy.springboot.datajpa.model.Category;
+
+public interface CategoryService {
+ Category create(Category category);
+
+ Category getById(Long id);
+
+ void delete(Long id);
+
+ Category update(Category category);
+}
diff --git a/src/main/java/mate/academy/springboot/datajpa/service/ProductService.java b/src/main/java/mate/academy/springboot/datajpa/service/ProductService.java
new file mode 100644
index 00000000..4c6ed90f
--- /dev/null
+++ b/src/main/java/mate/academy/springboot/datajpa/service/ProductService.java
@@ -0,0 +1,19 @@
+package mate.academy.springboot.datajpa.service;
+
+import java.math.BigDecimal;
+import java.util.List;
+import mate.academy.springboot.datajpa.model.Product;
+
+public interface ProductService {
+ Product create(Product product);
+
+ Product getById(Long id);
+
+ void delete(Long id);
+
+ Product update(Product product);
+
+ List findAllByPriceBetween(BigDecimal from, BigDecimal to);
+
+ List findAllByCategoryNameIn(List categories);
+}
diff --git a/src/main/java/mate/academy/springboot/datajpa/service/impl/CategoryServiceImpl.java b/src/main/java/mate/academy/springboot/datajpa/service/impl/CategoryServiceImpl.java
new file mode 100644
index 00000000..eeb1ba42
--- /dev/null
+++ b/src/main/java/mate/academy/springboot/datajpa/service/impl/CategoryServiceImpl.java
@@ -0,0 +1,39 @@
+package mate.academy.springboot.datajpa.service.impl;
+
+import java.util.NoSuchElementException;
+import mate.academy.springboot.datajpa.model.Category;
+import mate.academy.springboot.datajpa.repository.CategoryRepository;
+import mate.academy.springboot.datajpa.service.CategoryService;
+import org.springframework.stereotype.Service;
+
+@Service
+public class CategoryServiceImpl implements CategoryService {
+ private final CategoryRepository categoryRepository;
+
+ public CategoryServiceImpl(CategoryRepository categoryRepository) {
+ this.categoryRepository = categoryRepository;
+ }
+
+ @Override
+ public Category create(Category category) {
+ return categoryRepository.save(category);
+ }
+
+ @Override
+ public Category getById(Long id) {
+ return categoryRepository.findById(id).orElseThrow(
+ () -> new NoSuchElementException("Category not found with id " + id));
+ }
+
+ @Override
+ public void delete(Long id) {
+ categoryRepository.deleteById(id);
+ }
+
+ @Override
+ public Category update(Category category) {
+ Category categoryFromDb = getById(category.getId());
+ categoryFromDb.setName(category.getName());
+ return categoryRepository.save(categoryFromDb);
+ }
+}
diff --git a/src/main/java/mate/academy/springboot/datajpa/service/impl/ProductServiceImpl.java b/src/main/java/mate/academy/springboot/datajpa/service/impl/ProductServiceImpl.java
new file mode 100644
index 00000000..7cb4a7c9
--- /dev/null
+++ b/src/main/java/mate/academy/springboot/datajpa/service/impl/ProductServiceImpl.java
@@ -0,0 +1,53 @@
+package mate.academy.springboot.datajpa.service.impl;
+
+import java.math.BigDecimal;
+import java.util.List;
+import java.util.NoSuchElementException;
+import mate.academy.springboot.datajpa.model.Product;
+import mate.academy.springboot.datajpa.repository.ProductRepository;
+import mate.academy.springboot.datajpa.service.ProductService;
+import org.springframework.stereotype.Service;
+
+@Service
+public class ProductServiceImpl implements ProductService {
+ private final ProductRepository productRepository;
+
+ public ProductServiceImpl(ProductRepository productRepository) {
+ this.productRepository = productRepository;
+ }
+
+ @Override
+ public Product create(Product product) {
+ return productRepository.save(product);
+ }
+
+ @Override
+ public Product getById(Long id) {
+ return productRepository.findById(id).orElseThrow(
+ () -> new NoSuchElementException("Could not find product by id " + id));
+ }
+
+ @Override
+ public void delete(Long id) {
+ productRepository.deleteById(id);
+ }
+
+ @Override
+ public Product update(Product product) {
+ Product productFromDb = getById(product.getId());
+ productFromDb.setTitle(product.getTitle());
+ productFromDb.setPrice(product.getPrice());
+ productFromDb.setCategory(product.getCategory());
+ return productRepository.save(productFromDb);
+ }
+
+ @Override
+ public List findAllByPriceBetween(BigDecimal from, BigDecimal to) {
+ return productRepository.findAllByPriceBetween(from, to);
+ }
+
+ @Override
+ public List findAllByCategoryNameIn(List categories) {
+ return productRepository.findAllByCategoryNameIn(categories);
+ }
+}
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index 8b137891..82c683ad 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -1 +1,7 @@
+spring.datasource.url=jdbc:h2:mem:testdb
+spring.datasource.driverClassName=org.h2.Driver
+spring.datasource.username=sa
+spring.datasource.password=password
+spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
+spring.h2.console.enabled=true