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 extends Category> 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 extends Category> 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