-
Notifications
You must be signed in to change notification settings - Fork 343
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Created simple app for working with products and its categories #319
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package mate.academy.springboot.datajpa.config; | ||
|
||
import org.mapstruct.InjectionStrategy; | ||
import org.mapstruct.NullValueCheckStrategy; | ||
|
||
@org.mapstruct.MapperConfig( | ||
componentModel = "spring", | ||
injectionStrategy = InjectionStrategy.CONSTRUCTOR, | ||
nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS, | ||
implementationPackage = "<PACKAGE_NAME>.impl" | ||
) | ||
public class MapperConfig { | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
package mate.academy.springboot.datajpa.controller; | ||
|
||
import lombok.AllArgsConstructor; | ||
import mate.academy.springboot.datajpa.dto.CategoryRequestDto; | ||
import mate.academy.springboot.datajpa.dto.CategoryResponseDto; | ||
import mate.academy.springboot.datajpa.model.Category; | ||
import mate.academy.springboot.datajpa.service.CategoryService; | ||
import mate.academy.springboot.datajpa.service.mapper.DtoMapper; | ||
import org.springframework.web.bind.annotation.DeleteMapping; | ||
import org.springframework.web.bind.annotation.GetMapping; | ||
import org.springframework.web.bind.annotation.PatchMapping; | ||
import org.springframework.web.bind.annotation.PathVariable; | ||
import org.springframework.web.bind.annotation.PostMapping; | ||
import org.springframework.web.bind.annotation.RequestBody; | ||
import org.springframework.web.bind.annotation.RequestMapping; | ||
import org.springframework.web.bind.annotation.RestController; | ||
|
||
@RestController | ||
@RequestMapping("/categories") | ||
@AllArgsConstructor | ||
public class CategoryController { | ||
private final CategoryService categoryService; | ||
private final DtoMapper<CategoryResponseDto, Category, CategoryRequestDto> dtoMapper; | ||
|
||
@PostMapping | ||
public CategoryResponseDto add(@RequestBody CategoryRequestDto categoryRequestDto) { | ||
return dtoMapper.toDto( | ||
categoryService.create(dtoMapper.toEntity(categoryRequestDto))); | ||
} | ||
|
||
@GetMapping("/{id}") | ||
public CategoryResponseDto findById(@PathVariable Long id) { | ||
return dtoMapper.toDto(categoryService.findById(id)); | ||
} | ||
|
||
@PatchMapping("/{id}") | ||
public CategoryResponseDto update(@PathVariable Long id, | ||
@RequestBody CategoryRequestDto categoryRequestDto) { | ||
return dtoMapper.toDto(categoryService.update(id, | ||
dtoMapper.toEntity(categoryRequestDto))); | ||
} | ||
|
||
@DeleteMapping("/{id}") | ||
public void deleteById(@PathVariable Long id) { | ||
categoryService.deleteById(id); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,70 @@ | ||||||
package mate.academy.springboot.datajpa.controller; | ||||||
|
||||||
import java.math.BigDecimal; | ||||||
import java.util.List; | ||||||
import java.util.Set; | ||||||
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.model.Product; | ||||||
import mate.academy.springboot.datajpa.service.ProductService; | ||||||
import mate.academy.springboot.datajpa.service.mapper.DtoMapper; | ||||||
import org.springframework.http.HttpStatus; | ||||||
import org.springframework.web.bind.annotation.DeleteMapping; | ||||||
import org.springframework.web.bind.annotation.GetMapping; | ||||||
import org.springframework.web.bind.annotation.PatchMapping; | ||||||
import org.springframework.web.bind.annotation.PathVariable; | ||||||
import org.springframework.web.bind.annotation.PostMapping; | ||||||
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.ResponseStatus; | ||||||
import org.springframework.web.bind.annotation.RestController; | ||||||
|
||||||
@RestController | ||||||
@AllArgsConstructor | ||||||
@RequestMapping("/products") | ||||||
public class ProductController { | ||||||
private final ProductService productService; | ||||||
private final DtoMapper<ProductResponseDto, Product, ProductRequestDto> dtoMapper; | ||||||
|
||||||
@PostMapping | ||||||
public ProductResponseDto create(@RequestBody ProductRequestDto productRequestDto) { | ||||||
return dtoMapper.toDto( | ||||||
productService.create(dtoMapper.toEntity(productRequestDto))); | ||||||
} | ||||||
|
||||||
@GetMapping("/{id}") | ||||||
public ProductResponseDto get(@PathVariable Long id) { | ||||||
return dtoMapper.toDto(productService.findById(id)); | ||||||
} | ||||||
|
||||||
@PatchMapping("/{id}") | ||||||
public ProductResponseDto update(@PathVariable Long id, | ||||||
@RequestBody ProductRequestDto productRequestDto) { | ||||||
return dtoMapper.toDto(productService.update(id, | ||||||
dtoMapper.toEntity(productRequestDto))); | ||||||
} | ||||||
|
||||||
@DeleteMapping("/{id}") | ||||||
@ResponseStatus(HttpStatus.OK) | ||||||
public void delete(@PathVariable Long id) { | ||||||
productService.deleteById(id); | ||||||
} | ||||||
|
||||||
@GetMapping("/by-price") | ||||||
public List<ProductResponseDto> getAllByPriceBetween(@RequestParam BigDecimal priceFrom, | ||||||
@RequestParam BigDecimal priceTo) { | ||||||
return productService.getAllByPriceBetween(priceFrom, priceTo).stream() | ||||||
.map(dtoMapper::toDto) | ||||||
.collect(Collectors.toList()); | ||||||
} | ||||||
|
||||||
@GetMapping("/by-categories") | ||||||
public List<ProductResponseDto> getAllByCategoryIds(@RequestParam Set<Long> categoryIds) { | ||||||
List<Product> allByCategoryIds = productService.getAllByCategoryIds(categoryIds); | ||||||
return allByCategoryIds.stream() | ||||||
.map(dtoMapper::toDto).collect(Collectors.toList()); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, you are right. But I'm not using toList() in homework cos this method appears in Java 16 but most of our homework uses Java 11. I missed that this task is using Java 17. Also, I had some problems before with List immutability after using the "toList()" method, so... |
||||||
} | ||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package mate.academy.springboot.datajpa.dto; | ||
|
||
import lombok.Data; | ||
|
||
@Data | ||
public class CategoryRequestDto { | ||
private String name; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package mate.academy.springboot.datajpa.dto; | ||
|
||
import lombok.Data; | ||
|
||
@Data | ||
public class CategoryResponseDto { | ||
private Long id; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you need send id in response? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yep, I want to return the ID of the saved element |
||
private String name; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package mate.academy.springboot.datajpa.dto; | ||
|
||
import java.math.BigDecimal; | ||
import lombok.Data; | ||
|
||
@Data | ||
public class ProductResponseDto { | ||
private Long id; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The same, do you realy need send id in Response? |
||
private String title; | ||
private BigDecimal price; | ||
private Long categoryId; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
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.Table; | ||
import lombok.Getter; | ||
import lombok.Setter; | ||
|
||
@Getter | ||
@Setter | ||
@Entity | ||
@Table(name = "categories") | ||
public class Category { | ||
@Id | ||
@GeneratedValue(strategy = GenerationType.IDENTITY) | ||
private Long id; | ||
private String name; | ||
} |
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
@@ -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 | ||||||||
Comment on lines
+13
to
+14
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can use one annotation Data
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||||||||
@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; | ||||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<Category, Long> { | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package mate.academy.springboot.datajpa.repository; | ||
|
||
import java.math.BigDecimal; | ||
import java.util.Collection; | ||
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<Product, Long> { | ||
List<Product> getAllByPriceBetween(BigDecimal priceFrom, BigDecimal priceTo); | ||
|
||
List<Product> getAllByCategoryIdIn(Collection<Long> categoryId); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 findById(Long id); | ||
|
||
Category update(Long id, Category category); | ||
|
||
void deleteById(Long id); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package mate.academy.springboot.datajpa.service; | ||
|
||
import java.util.NoSuchElementException; | ||
import lombok.AllArgsConstructor; | ||
import mate.academy.springboot.datajpa.model.Category; | ||
import mate.academy.springboot.datajpa.repository.CategoryRepository; | ||
import org.springframework.stereotype.Service; | ||
|
||
@Service | ||
@AllArgsConstructor | ||
public class CategoryServiceImpl implements CategoryService { | ||
private final CategoryRepository categoryRepository; | ||
|
||
@Override | ||
public Category create(Category category) { | ||
return categoryRepository.save(category); | ||
} | ||
|
||
@Override | ||
public Category findById(Long id) { | ||
return categoryRepository.findById(id).orElseThrow(() -> | ||
new NoSuchElementException("Can't get category with id " + id)); | ||
} | ||
|
||
@Override | ||
public Category update(Long id, Category category) { | ||
if (category == null) { | ||
throw new IllegalArgumentException("Category cannot be null"); | ||
} | ||
Category categoryFromDb = categoryRepository.findById(id).orElseThrow(() -> | ||
new NoSuchElementException("Can't get category with id " + id)); | ||
categoryFromDb.setName(category.getName()); | ||
return categoryRepository.save(categoryFromDb); | ||
} | ||
|
||
@Override | ||
public void deleteById(Long id) { | ||
categoryRepository.deleteById(id); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can use short option