diff --git a/docker-compose-db.yml b/docker-compose-db.yml new file mode 100644 index 0000000..a2014aa --- /dev/null +++ b/docker-compose-db.yml @@ -0,0 +1,12 @@ +version: '3.8' +services: + web_db: + image: postgres + container_name: spring_db + environment: + - POSTGRES_DB=localdb + - POSTGRES_PASSWORD=localdb + - POSTGRES_USER=localdb + restart: always + ports: + - '5430:5432' \ No newline at end of file diff --git a/pom.xml b/pom.xml index 9a6e07f..920a90f 100644 --- a/pom.xml +++ b/pom.xml @@ -31,11 +31,11 @@ spring-boot-starter-web - - - - - + + org.postgresql + postgresql + runtime + org.projectlombok lombok @@ -62,6 +62,10 @@ tomcat-embed-core 10.1.13 + + org.springframework.boot + spring-boot-starter-data-jpa + diff --git a/src/main/java/com/example/springlabs/configuration/StoreConfiguration.java b/src/main/java/com/example/springlabs/configuration/StoreConfiguration.java deleted file mode 100644 index c852a0a..0000000 --- a/src/main/java/com/example/springlabs/configuration/StoreConfiguration.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.example.springlabs.configuration; - - -import com.example.springlabs.model.Category; -import com.example.springlabs.model.User; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; -import java.io.FileInputStream; -import java.io.InputStream; -import java.util.List; -import lombok.AccessLevel; -import lombok.SneakyThrows; -import lombok.experimental.FieldDefaults; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -@Configuration -@FieldDefaults(level = AccessLevel.PRIVATE) -public class StoreConfiguration { - - final ObjectMapper objectMapper = new ObjectMapper(); - - @Value("${path.data}") - String pathData; - - @Value("${path.users}") - String pathUsers; - - @SneakyThrows - @Bean - List categories() { - try (InputStream inputStream = new FileInputStream(pathData)) { - return objectMapper.readValue(inputStream, new TypeReference<>() {}); - } - } - - @SneakyThrows - @Bean - List users() { - try (InputStream inputStream = new FileInputStream(pathUsers)) { - return objectMapper.readValue(inputStream, new TypeReference<>() {}); - } - } -} diff --git a/src/main/java/com/example/springlabs/controllers/CategoryController.java b/src/main/java/com/example/springlabs/controllers/CategoryController.java index 07677a6..23a28b4 100644 --- a/src/main/java/com/example/springlabs/controllers/CategoryController.java +++ b/src/main/java/com/example/springlabs/controllers/CategoryController.java @@ -2,6 +2,8 @@ import com.example.springlabs.controllers.dtos.CategoryDto; import com.example.springlabs.controllers.dtos.mappers.CategoryDtoMapper; +import com.example.springlabs.exception.CategoryNotFoundException; +import com.example.springlabs.model.Category; import com.example.springlabs.services.CategoryService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -11,132 +13,121 @@ import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.servlet.http.HttpServletRequest; + import java.net.URLDecoder; import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; +import java.util.*; + import lombok.AccessLevel; import lombok.RequiredArgsConstructor; import lombok.experimental.FieldDefaults; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.util.AntPathMatcher; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -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.ResponseStatus; -import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.*; import org.springframework.web.servlet.HandlerMapping; @Tag(name = "Category", description = "Operations related to categories") @RestController -@RequestMapping(value = "/categories", produces = MediaType.APPLICATION_JSON_VALUE) +@RequestMapping(value = "/categories", produces = MediaType.APPLICATION_JSON_VALUE) @RequiredArgsConstructor @FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) public class CategoryController { - CategoryService categoryService; + CategoryService categoryService; + + CategoryDtoMapper categoryDtoMapper; - CategoryDtoMapper categoryDtoMapper; + String CATEGORY_NAME_NOT_FOUND = "Category with name: %s doesn't exist!"; - @Operation(summary = "Get all categories", description = "Returns a list of all categories.", parameters = { - @Parameter(name = "page", description = "Page number starting from 0"), - @Parameter(name = "size", description = "Size of page"), - @Parameter(name = "name", description = "Value for filtering by category name") - }) - @ApiResponse(responseCode = "200", description = "Successful given categories", - content = @Content(schema = @Schema(implementation = CategoryDto.class))) - @GetMapping - public Collection getAll(@RequestParam(value = "page", defaultValue = "0") int page, - @RequestParam(value = "size", defaultValue = "0") int size, - @RequestParam(value = "name", defaultValue = "") String name) { - return categoryDtoMapper.createDtosSet(categoryService.getAllCategories(page, size, name)); - } + @Operation(summary = "Get all categories", description = "Returns a list of all categories.", parameters = { + @Parameter(name = "page", description = "Page number starting from 0"), + @Parameter(name = "size", description = "Size of page"), + @Parameter(name = "name", description = "Value for filtering by category name") + }) + @ApiResponse(responseCode = "200", description = "Successful given categories", + content = @Content(schema = @Schema(implementation = CategoryDto.class))) + @GetMapping + public Collection getAll(@RequestParam(value = "page", defaultValue = "0") int page, + @RequestParam(value = "size", defaultValue = "0") int size, + @RequestParam(value = "name", defaultValue = "") String name) { + return categoryDtoMapper.createDtosSet(categoryService.getAllCategories(page, size, name)); + } - @Operation(summary = "Get a category by name", description = "Returns a category by its name.") - @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "Successful returned category", - content = @Content(schema = @Schema(implementation = CategoryDto.class))), - @ApiResponse(responseCode = "404", description = "Category not found by name", content = @Content) - }) - @GetMapping("/**") - public CategoryDto getCategory(HttpServletRequest request) { - List urlComponents = getUrlComponents(request); - return categoryDtoMapper.createDto(categoryService.getCategoryByName(urlComponents)); - } + @Operation(summary = "Get a category by name", description = "Returns a category by its name.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "Successful returned category", + content = @Content(schema = @Schema(implementation = CategoryDto.class))), + @ApiResponse(responseCode = "404", description = "Category not found by name", content = @Content) + }) + @GetMapping("/**") + public CategoryDto getCategory(HttpServletRequest request) { + List urlComponents = getUrlComponents(request); + return categoryDtoMapper.createDto(categoryService.getCategoryByName(urlComponents)); + } - @Operation(summary = "Add a new category", description = "Creates a new category.") - @ApiResponses(value = { - @ApiResponse(responseCode = "201", description = "A new category created", content = @Content(schema = @Schema(implementation = CategoryDto.class))), - @ApiResponse(responseCode = "400", description = "Invalid request data", content = @Content) - }) - @PostMapping - @ResponseStatus(HttpStatus.CREATED) - public CategoryDto addCategory(@RequestBody CategoryDto categoryDto) { - return categoryDtoMapper.createDto( - categoryService.addCategory(categoryDtoMapper.createCategoryFromDto(categoryDto))); - } + @Operation(summary = "Add a new category", description = "Creates a new category.") + @ApiResponses(value = { + @ApiResponse(responseCode = "201", description = "A new category created", content = @Content(schema = @Schema(implementation = CategoryDto.class))), + @ApiResponse(responseCode = "400", description = "Invalid request data", content = @Content) + }) + @PostMapping + @ResponseStatus(HttpStatus.CREATED) + public CategoryDto addCategory(@RequestBody CategoryDto categoryDto) { + return categoryDtoMapper.createDto( + categoryService.addCategory(categoryDtoMapper.createCategoryFromDto(categoryDto))); + } - @Operation(summary = "Add a subcategory to a category", description = "Creates a new subcategory for the specified category.") - @ApiResponses(value = { - @ApiResponse(responseCode = "201", description = "New subcategory for the specified category created", - content = @Content(schema = @Schema(implementation = CategoryDto.class))), - @ApiResponse(responseCode = "400", description = "Invalid request data", content = @Content), - @ApiResponse(responseCode = "404", description = "Parent category is not found by name", content = @Content) - }) - @PostMapping("/**") - @ResponseStatus(HttpStatus.CREATED) - public CategoryDto addSubcategory(HttpServletRequest request, - @RequestBody CategoryDto categoryDto) { - List urlComponents = getUrlComponents(request); - return categoryDtoMapper.createDto( - categoryService.addSubcategory(urlComponents, - categoryDtoMapper.createCategoryFromDto(categoryDto))); - } + @Operation(summary = "Add a subcategory to a category", description = "Creates a new subcategory for the specified category.") + @ApiResponses(value = { + @ApiResponse(responseCode = "201", description = "New subcategory for the specified category created", + content = @Content(schema = @Schema(implementation = CategoryDto.class))), + @ApiResponse(responseCode = "400", description = "Invalid request data", content = @Content), + @ApiResponse(responseCode = "404", description = "Parent category is not found by name", content = @Content) + }) + @PostMapping("/**") + @ResponseStatus(HttpStatus.CREATED) + public CategoryDto addSubcategory(HttpServletRequest request, + @RequestBody CategoryDto categoryDto) { + List urlComponents = getUrlComponents(request); + return categoryDtoMapper.createDto(categoryService.addCategory(categoryDtoMapper.createCategoryFromDto(categoryDto), urlComponents)); + } - @Operation(summary = "Update a category", description = "Updates an existing category.") - @ApiResponses({ - @ApiResponse(responseCode = "200", description = "Category updated", - content = @Content(schema = @Schema(implementation = CategoryDto.class))), - @ApiResponse(responseCode = "400", description = "Invalid category or request data", content = @Content), - @ApiResponse(responseCode = "404", description = "Category is not found by id", content = @Content) - }) - @PutMapping("/**") - @ResponseStatus(HttpStatus.OK) - public CategoryDto updateCategory(HttpServletRequest request, - @RequestBody CategoryDto categoryDto) { - List urlComponents = new ArrayList<>(getUrlComponents(request)); - String id = urlComponents.remove(urlComponents.size() - 1); - return categoryDtoMapper.createDto( - categoryService.updateCategory(urlComponents, id, - categoryDtoMapper.createCategoryFromDto(categoryDto))); - } + @Operation(summary = "Update a category", description = "Updates an existing category.") + @ApiResponses({ + @ApiResponse(responseCode = "200", description = "Category updated", + content = @Content(schema = @Schema(implementation = CategoryDto.class))), + @ApiResponse(responseCode = "400", description = "Invalid category or request data", content = @Content), + @ApiResponse(responseCode = "404", description = "Category is not found by id", content = @Content) + }) + @PutMapping("/**") + @ResponseStatus(HttpStatus.OK) + public CategoryDto updateCategory(HttpServletRequest request, + @RequestBody CategoryDto categoryDto) { + List urlComponents = new ArrayList<>(getUrlComponents(request)); + String id = urlComponents.remove(urlComponents.size() - 1); + return categoryDtoMapper.createDto( + categoryService.updateCategory(urlComponents, id, + categoryDtoMapper.createCategoryFromDto(categoryDto))); + } - @Operation(summary = "Delete a category", description = "Deletes an existing category.") - @ApiResponses({ - @ApiResponse(responseCode = "204", description = "Category was successfully deleted"), - @ApiResponse(responseCode = "404", description = "Category is not found by id")}) - @DeleteMapping("/**") - @ResponseStatus(HttpStatus.NO_CONTENT) - public void deleteCategory(HttpServletRequest request) { - List urlComponents = new ArrayList<>(getUrlComponents(request)); - String id = urlComponents.remove(urlComponents.size() - 1); - categoryService.deleteCategory(urlComponents, id); - } + @Operation(summary = "Delete a category", description = "Deletes an existing category.") + @ApiResponses({ + @ApiResponse(responseCode = "204", description = "Category was successfully deleted"), + @ApiResponse(responseCode = "404", description = "Category is not found by id")}) + @DeleteMapping("/{id}") + @ResponseStatus(HttpStatus.NO_CONTENT) + public void deleteCategory(@PathVariable long id) { + categoryService.deleteCategory(id); + } - private List getUrlComponents(HttpServletRequest request) { - return Arrays.stream(new AntPathMatcher().extractPathWithinPattern( - request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE).toString(), - URLDecoder.decode( - request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE).toString(), - Charset.defaultCharset())) - .split("/")) - .toList(); - } + private List getUrlComponents(HttpServletRequest request) { + return Arrays.stream(new AntPathMatcher().extractPathWithinPattern( + request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE).toString(), + URLDecoder.decode( + request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE).toString(), + Charset.defaultCharset())) + .split("/")) + .toList(); + } } \ No newline at end of file diff --git a/src/main/java/com/example/springlabs/model/Category.java b/src/main/java/com/example/springlabs/model/Category.java index 7d9b064..0026520 100644 --- a/src/main/java/com/example/springlabs/model/Category.java +++ b/src/main/java/com/example/springlabs/model/Category.java @@ -5,22 +5,28 @@ import java.util.List; import java.util.Set; import java.util.TreeSet; -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; +import jakarta.persistence.*; +import lombok.*; + +@Entity(name = "categories") +@NamedQuery(name = "Categories.getCategoryById", + query = "SELECT u FROM categories u WHERE u.id = :id") @Getter @Setter @ToString @EqualsAndHashCode @NoArgsConstructor + public class Category implements Comparable { - private static long nextId = 10; // temporary solution for id generation - private long id = nextId++; + @Id + @GeneratedValue(strategy= GenerationType.AUTO) + private long id; + @Column(nullable = false) private String name; + @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL) private Set subCategories = new TreeSet<>(); + @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL) private List products = new ArrayList<>(); public Category(String name, Set subCategories, List products) { @@ -29,10 +35,8 @@ public Category(String name, Set subCategories, List products this.products = products; } - @Override public int compareTo(Category o) { return this.name.compareTo(o.name); } -} - +} \ No newline at end of file diff --git a/src/main/java/com/example/springlabs/model/Product.java b/src/main/java/com/example/springlabs/model/Product.java index 43e5e53..e4108cc 100644 --- a/src/main/java/com/example/springlabs/model/Product.java +++ b/src/main/java/com/example/springlabs/model/Product.java @@ -1,26 +1,23 @@ package com.example.springlabs.model; -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; +import jakarta.persistence.*; +import lombok.*; +@Entity @NoArgsConstructor +@AllArgsConstructor @Getter @Setter @ToString @EqualsAndHashCode public class Product { - private static long nextId = 10; // temporary solution for id generation - private long id = nextId++; + @Id + @GeneratedValue(strategy= GenerationType.AUTO) + private long id; + @Column(nullable = false) private String name; + @Column(nullable = false) private double price; - - public Product(String name, double price) { - this.name = name; - this.price = price; - } } diff --git a/src/main/java/com/example/springlabs/model/User.java b/src/main/java/com/example/springlabs/model/User.java index 2a1afb5..8d27293 100644 --- a/src/main/java/com/example/springlabs/model/User.java +++ b/src/main/java/com/example/springlabs/model/User.java @@ -1,5 +1,6 @@ package com.example.springlabs.model; +import jakarta.persistence.*; import lombok.AllArgsConstructor; import lombok.EqualsAndHashCode; import lombok.Getter; @@ -7,6 +8,9 @@ import lombok.Setter; import lombok.ToString; +@Entity(name = "users") +@NamedQuery(name = "Users.getUserById", + query = "SELECT u FROM users u WHERE u.id = :id") @Getter @Setter @ToString @@ -14,11 +18,17 @@ @NoArgsConstructor @AllArgsConstructor public class User { - private static long nextId = 10; // temporary solution for id generation - private long id = nextId++; + @Id + @GeneratedValue(strategy= GenerationType.AUTO) + private long id; + @Column(nullable = false) private String name; + @Column(nullable = false) private String surname; + @Column(nullable = false, unique = true) private String email; + @Column(nullable = false) private String password; + @Column(nullable = false) private boolean isAdmin; } diff --git a/src/main/java/com/example/springlabs/repositories/CategoryRepository.java b/src/main/java/com/example/springlabs/repositories/CategoryRepository.java index 1c50fd3..fd00629 100644 --- a/src/main/java/com/example/springlabs/repositories/CategoryRepository.java +++ b/src/main/java/com/example/springlabs/repositories/CategoryRepository.java @@ -1,21 +1,38 @@ package com.example.springlabs.repositories; import com.example.springlabs.model.Category; -import java.util.Collection; +import jakarta.transaction.Transactional; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import org.springframework.lang.Nullable; + import java.util.List; import java.util.Optional; -public interface CategoryRepository { - List getCategories(); +public interface CategoryRepository extends JpaRepository { - void addCategory(Category category); + //find by id - @NamedEntity + @Query(nativeQuery = true, name = "Categories.getCategoryById") + Category getCategoryById(@Param("id") Long id); - Category getCategoryById(long id); + // read all - jpa + List findAll(); - Optional updateCategory(long id, Category newCategory, - Collection subcategories); + // Delete - @Query + @Modifying + @Transactional + @Query("DELETE FROM categories u WHERE u.id = :id") + void deleteCategory(@Param("id") Long id); - void deleteCategory(long id, Collection subcategories); + //getCategoryByName + @Query(value = "SELECT * FROM categories c WHERE c.name = :name", nativeQuery = true) + Optional getCategoryByName(@Param("name") String name); - Optional getCategoryByName(String name); + //addCategory + @Transactional + @Modifying + @Query(value = "INSERT INTO categories (name, parentCategoryId) VALUES (:name, :parentId)", nativeQuery = true) + void insertCategory(@Param("name") String name, @Param("parentId") Long parentId); } diff --git a/src/main/java/com/example/springlabs/repositories/CategoryRepositoryImpl.java b/src/main/java/com/example/springlabs/repositories/CategoryRepositoryImpl.java deleted file mode 100644 index ffcf53f..0000000 --- a/src/main/java/com/example/springlabs/repositories/CategoryRepositoryImpl.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.example.springlabs.repositories; - -import com.example.springlabs.model.Category; -import java.util.Collection; -import java.util.List; -import java.util.Optional; -import lombok.AccessLevel; -import lombok.RequiredArgsConstructor; -import lombok.experimental.FieldDefaults; -import org.springframework.stereotype.Repository; - -@Repository -@RequiredArgsConstructor -@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) -public class CategoryRepositoryImpl implements CategoryRepository { - - List categories; - - @Override - public List getCategories() { - return categories; - } - - @Override - public void addCategory(Category category) { - categories.add(category); - } - - @Override - public Category getCategoryById(long id) { - return categories.stream() - .filter(category -> category.getId() == id) - .findFirst() - .orElse(null); - } - - @Override - public Optional updateCategory(long id, Category newCategory, - Collection subcategories) { - Collection categoriesToIterate = - subcategories.isEmpty() ? categories : subcategories; - - for (Category category : categoriesToIterate) { - if (category.getId() == id) { - category.setName(newCategory.getName()); - category.setSubCategories(newCategory.getSubCategories()); - category.setProducts(newCategory.getProducts()); - return Optional.of(category); - } - } - return Optional.empty(); - } - - @Override - public void deleteCategory(long id, Collection subcategories) { - Collection categoriesToIterate = - subcategories.isEmpty() ? categories : subcategories; - categoriesToIterate.removeIf(category -> category.getId() == id); - } - - @Override - public Optional getCategoryByName(String name) { - return categories.stream() - .filter(category -> category.getName().equals(name)) - .findFirst(); - } -} diff --git a/src/main/java/com/example/springlabs/repositories/UserRepository.java b/src/main/java/com/example/springlabs/repositories/UserRepository.java index 3135e5d..c683619 100644 --- a/src/main/java/com/example/springlabs/repositories/UserRepository.java +++ b/src/main/java/com/example/springlabs/repositories/UserRepository.java @@ -1,17 +1,32 @@ package com.example.springlabs.repositories; import com.example.springlabs.model.User; -import java.util.List; +import jakarta.transaction.Transactional; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; -public interface UserRepository { +import java.util.List; - List getUsers(); +public interface UserRepository extends JpaRepository { - void deleteUserById(long id); + //find by id - @NamedEntity + @Query(nativeQuery = true, name = "Users.getUserById") + User getUserById(@Param("id") Long id); - User getUserById(long id); + // read all - jpa + List findAll(); - void updateUser(User updatedUser); + // Update - @Query + @Modifying + @Transactional + @Query("UPDATE users u SET u.name = :name, u.surname = :surname, u.email = :email, u.password = :password, u.isAdmin = :isAdmin WHERE u.id = :id") + void updateUser(@Param("id") Long id, @Param("name") String name, @Param("surname") String surname, @Param("email") String email, @Param("password") String password, @Param("isAdmin") boolean isAdmin); - void addUser(User user); + // Delete - @Query + @Modifying + @Transactional + @Query("DELETE FROM users u WHERE u.id = :id") + void deleteUserById(@Param("id") Long id); } diff --git a/src/main/java/com/example/springlabs/repositories/UserRepositoryImpl.java b/src/main/java/com/example/springlabs/repositories/UserRepositoryImpl.java deleted file mode 100644 index 7a643cf..0000000 --- a/src/main/java/com/example/springlabs/repositories/UserRepositoryImpl.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.example.springlabs.repositories; - -import com.example.springlabs.model.User; -import java.util.List; -import lombok.AccessLevel; -import lombok.RequiredArgsConstructor; -import lombok.experimental.FieldDefaults; -import org.springframework.stereotype.Repository; - -@Repository -@RequiredArgsConstructor -@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) -public class UserRepositoryImpl implements UserRepository{ - List users; - - @Override - public List getUsers() { - return users; - } - - @Override - public void deleteUserById(long id) { - users.removeIf(user -> user.getId() == id); - } - - @Override - public User getUserById(long id) { - return users.stream() - .filter(user -> user.getId() == id) - .findFirst() - .orElse(null); - } - - @Override - public void updateUser(User updatedUser) { - for (User user : users) { - if (user.getId() == updatedUser.getId()) { - user.setName(updatedUser.getName()); - user.setSurname(updatedUser.getSurname()); - user.setEmail(updatedUser.getEmail()); - user.setPassword(updatedUser.getPassword()); - user.setAdmin(updatedUser.isAdmin()); - break; - } - } - } - - @Override - public void addUser(User user) { - users.add(user); - } -} - - diff --git a/src/main/java/com/example/springlabs/services/CategoryService.java b/src/main/java/com/example/springlabs/services/CategoryService.java index 8d525d4..a22e825 100644 --- a/src/main/java/com/example/springlabs/services/CategoryService.java +++ b/src/main/java/com/example/springlabs/services/CategoryService.java @@ -3,10 +3,12 @@ import com.example.springlabs.exception.CategoryNotFoundException; import com.example.springlabs.model.Category; import com.example.springlabs.repositories.CategoryRepository; +import jakarta.transaction.Transactional; import lombok.AccessLevel; import lombok.RequiredArgsConstructor; import lombok.experimental.FieldDefaults; import org.springframework.stereotype.Service; + import java.util.Collection; import java.util.List; import java.util.Optional; @@ -16,34 +18,34 @@ @FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) public class CategoryService { - CategoryRepository categoryRepository; - - String CATEGORY_NAME_NOT_FOUND = "Category with name: %s doesn't exist!"; - String CATEGORY_ID_NOT_FOUND = "Category with id: %s doesn't exist!"; + CategoryRepository categoryRepository; - public List getAllCategories() { - return categoryRepository.getCategories(); - } + String CATEGORY_NAME_NOT_FOUND = "Category with name: %s doesn't exist!"; + String CATEGORY_ID_NOT_FOUND = "Category with id: %s doesn't exist!"; - public Category addCategory(Category category) { - categoryRepository.addCategory(category); - return category; - } + public List getAllCategories() { + return categoryRepository.findAll(); + } - public Category addSubcategory(List categoriesNames, Category categoryFromDto) { - getSubcategories(categoriesNames).add(categoryFromDto); - return categoryFromDto; - } + @Transactional + public Category addCategory(Category category) { + return categoryRepository.save(category); + } - public Collection getSubcategories(List categoriesNames) { - return getCategoryByName(categoriesNames).getSubCategories(); + public Category addCategory(Category category, List categoriesNames) { + categoryRepository.insertCategory(category.getName(), getCategoryByName(categoriesNames).getId()); + Optional returnedCategory = categoryRepository.getCategoryByName(category.getName()); + if (returnedCategory.isEmpty()) { + throw new CategoryNotFoundException( + CATEGORY_NAME_NOT_FOUND.formatted("Category is empty")); + } else return returnedCategory.get(); } - private Optional getSubcategoryByName(Category category, String name) { - return category.getSubCategories().stream() - .filter(subCategory -> subCategory.getName().equals(name)) - .findFirst(); - } + private Optional getSubcategoryByName(Category category, String name) { + return category.getSubCategories().stream() + .filter(subCategory -> subCategory.getName().equals(name)) + .findFirst(); + } public Category getCategoryByName(List categoriesNamesPath) { Optional parentCategory = categoryRepository.getCategoryByName(categoriesNamesPath.get(0)); @@ -54,31 +56,30 @@ public Category getCategoryByName(List categoriesNamesPath) { } parentCategory = getSubcategoryByName(parentCategory.get(), categoriesNamesPath.get(i)); } - return parentCategory.orElseThrow( () -> new CategoryNotFoundException( CATEGORY_NAME_NOT_FOUND.formatted(categoriesNamesPath.get(categoriesNamesPath.size() - 1)))); } + @Transactional public Category updateCategory(List categoriesNames, String stringId, Category categoryFromDto) { - long id = saveParseId(stringId); - return categoryRepository.updateCategory(id, categoryFromDto, getSubcategories(categoriesNames)) - .orElseThrow(() -> new CategoryNotFoundException(CATEGORY_ID_NOT_FOUND.formatted(stringId))); + getCategoryByName(categoriesNames); + categoryFromDto.setId(saveParseId(stringId)); + return categoryRepository.save(categoryFromDto); } - public void deleteCategory(List categoriesNames, String stringId) { - long id = saveParseId(stringId); - categoryRepository.deleteCategory(id, getSubcategories(categoriesNames)); - } + public void deleteCategory(long id) { + categoryRepository.deleteCategory(id); + } - private long saveParseId(String s) { - try { - return Long.parseLong(s); - } catch (NumberFormatException e) { - throw new CategoryNotFoundException(CATEGORY_ID_NOT_FOUND.formatted(s), e); - } - } + private long saveParseId(String s) { + try { + return Long.parseLong(s); + } catch (NumberFormatException e) { + throw new CategoryNotFoundException(CATEGORY_ID_NOT_FOUND.formatted(s), e); + } + } public Collection getAllCategories(int page, int size, String name) { Collection categories = getAllCategories().stream().filter(c -> c.getName().contains(name)).toList(); diff --git a/src/main/java/com/example/springlabs/services/UserService.java b/src/main/java/com/example/springlabs/services/UserService.java index a10659a..edf3a53 100644 --- a/src/main/java/com/example/springlabs/services/UserService.java +++ b/src/main/java/com/example/springlabs/services/UserService.java @@ -2,7 +2,10 @@ import com.example.springlabs.model.User; import com.example.springlabs.repositories.UserRepository; + import java.util.List; + +import jakarta.transaction.Transactional; import lombok.AccessLevel; import lombok.RequiredArgsConstructor; import lombok.experimental.FieldDefaults; @@ -15,26 +18,25 @@ public class UserService { UserRepository userRepository; public List getAllUsers() { - return userRepository.getUsers(); + return userRepository.findAll(); } - public User getUserById(long id) { - return userRepository.getUserById(id); + @Transactional + public void updateUser(Long id, String name, String surname, String email, String password, boolean isAdmin) { + userRepository.updateUser(id, name, surname, email, password, isAdmin); } - public List deleteUserById(long id) { + public void deleteUserById(Long id) { userRepository.deleteUserById(id); - return userRepository.getUsers(); } - public List updateUser(User updatedUser) { - userRepository.updateUser(updatedUser); - return userRepository.getUsers(); + @Transactional + public User addUser(User user) { + return userRepository.save(user); } - public List addUser(User user) { - userRepository.addUser(user); - return userRepository.getUsers(); + public User getUserById(long id) { + return userRepository.getUserById(id); } } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 8b854b2..f27ac9c 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,2 +1,10 @@ path.data=src/main/resources/data.json -path.users=src/main/resources/users.json \ No newline at end of file +path.users=src/main/resources/users.json +#server.port=8081 + +spring.datasource.url=jdbc:postgresql://localhost:5430/localdb +spring.datasource.username=localdb +spring.datasource.password=localdb +spring.jpa.hibernate.ddl-auto=create +spring.jpa.show-sql=true +spring.jpa.properties.hibernate.format_sql=true \ No newline at end of file diff --git a/start.sh b/start.sh new file mode 100644 index 0000000..05f0a1e --- /dev/null +++ b/start.sh @@ -0,0 +1,13 @@ +#!/bin/bash +docker-compose -f docker-compose-db.yml -p abc up -d +sleep 10 + +#docker exec -i spring_db psql -U localdb -d localdb < src/main/resources/schema.sql +#docker exec -i spring_db psql -U localdb -d localdb < src/main/resources/data.sql + +sed -i 's|spring.datasource.url=.*|spring.datasource.url=jdbc:postgresql://localhost:5430/localdb|' src/main/resources/application.properties +sed -i 's|spring.datasource.username=.*|spring.datasource.username=localdb|' src/main/resources/application.properties +sed -i 's|spring.datasource.password=.*|spring.datasource.password=localdb|' src/main/resources/application.properties + +#./mvnw clean install -D skipTests +#java -jar target/spring-labs-0.0.1-SNAPSHOT.jar