diff --git a/demo/src/main/java/com/example/demo/core/config/Constants.java b/demo/src/main/java/com/example/demo/config/Constants.java similarity index 79% rename from demo/src/main/java/com/example/demo/core/config/Constants.java rename to demo/src/main/java/com/example/demo/config/Constants.java index 454f0de..32ce500 100644 --- a/demo/src/main/java/com/example/demo/core/config/Constants.java +++ b/demo/src/main/java/com/example/demo/config/Constants.java @@ -1,4 +1,4 @@ -package com.example.demo.core.config; +package com.example.demo.config; public class Constants { public static final String SEQUENCE_NAME = "hibernate_sequence"; diff --git a/demo/src/main/java/com/example/demo/core/config/WebConfiguration.java b/demo/src/main/java/com/example/demo/config/WebConfiguration.java similarity index 92% rename from demo/src/main/java/com/example/demo/core/config/WebConfiguration.java rename to demo/src/main/java/com/example/demo/config/WebConfiguration.java index 2570aef..f2ca020 100644 --- a/demo/src/main/java/com/example/demo/core/config/WebConfiguration.java +++ b/demo/src/main/java/com/example/demo/config/WebConfiguration.java @@ -1,4 +1,4 @@ -package com.example.demo.core.config; +package com.example.demo.config; import org.springframework.context.annotation.Configuration; import org.springframework.lang.NonNull; diff --git a/demo/src/main/java/com/example/demo/controllers/CustomerController.java b/demo/src/main/java/com/example/demo/controllers/CustomerController.java index d4a7918..9a97fe3 100644 --- a/demo/src/main/java/com/example/demo/controllers/CustomerController.java +++ b/demo/src/main/java/com/example/demo/controllers/CustomerController.java @@ -2,7 +2,7 @@ package com.example.demo.controllers; import java.util.List; -import com.example.demo.core.config.Constants; +import com.example.demo.config.Constants; import com.example.demo.dtos.GameDto; import com.example.demo.dtos.PlayDto; import com.example.demo.services.GameService; @@ -55,14 +55,4 @@ public class CustomerController { public GameDto createGame(@PathVariable(name = "id") long id, @RequestBody GameDto game){ return new GameDto(gameService.addGame(id, game.getName(), game.getDescription())); } - - @GetMapping("/{id}/games") - public List getGames(@PathVariable(name = "id") long id){ - return customerService.findCustomer(id).getGames().stream().map(GameDto::new).toList(); - } - - @GetMapping("/{id}/plays") - public List getPlays(@PathVariable(name = "id") long id){ - return customerService.findCustomer(id).getPlays().stream().map(PlayDto::new).toList(); - } } diff --git a/demo/src/main/java/com/example/demo/controllers/GameController.java b/demo/src/main/java/com/example/demo/controllers/GameController.java index c844470..255d089 100644 --- a/demo/src/main/java/com/example/demo/controllers/GameController.java +++ b/demo/src/main/java/com/example/demo/controllers/GameController.java @@ -1,6 +1,6 @@ package com.example.demo.controllers; -import com.example.demo.core.config.Constants; +import com.example.demo.config.Constants; import com.example.demo.dtos.GameDto; import com.example.demo.dtos.PlayDto; import com.example.demo.services.GameService; diff --git a/demo/src/main/java/com/example/demo/controllers/PlayController.java b/demo/src/main/java/com/example/demo/controllers/PlayController.java index 8dfa64d..7d9980e 100644 --- a/demo/src/main/java/com/example/demo/controllers/PlayController.java +++ b/demo/src/main/java/com/example/demo/controllers/PlayController.java @@ -1,9 +1,8 @@ package com.example.demo.controllers; -import com.example.demo.core.config.Constants; +import com.example.demo.config.Constants; import com.example.demo.dtos.CustomerDto; import com.example.demo.dtos.PlayDto; -import com.example.demo.models.Customer; import com.example.demo.services.PlayService; import org.springframework.web.bind.annotation.*; @@ -46,9 +45,4 @@ public class PlayController { public boolean addCustomer(@PathVariable(name = "id") long id, @RequestParam long customerId){ return playService.addCustomer(id, customerId); } - - @GetMapping("/{id}/customers") - public List getCustomers(@PathVariable(name = "id") long id){ - return playService.findPlay(id).getCustomers().stream().map(CustomerDto::new).toList(); - } } diff --git a/demo/src/main/java/com/example/demo/dtos/CustomerDto.java b/demo/src/main/java/com/example/demo/dtos/CustomerDto.java index 6716dd2..5eb033f 100644 --- a/demo/src/main/java/com/example/demo/dtos/CustomerDto.java +++ b/demo/src/main/java/com/example/demo/dtos/CustomerDto.java @@ -1,5 +1,7 @@ package com.example.demo.dtos; import com.example.demo.models.Customer; +import com.example.demo.models.Game; +import com.example.demo.models.Play; import jakarta.validation.constraints.*; import java.util.ArrayList; @@ -13,9 +15,9 @@ public class CustomerDto { @Min(2) private String name; - private List games; + private List gamesId; - private List plays; + private List playsId; public CustomerDto(){ @@ -28,18 +30,18 @@ public class CustomerDto { var existGames = customer.getGames(); if (existGames != null && !existGames.isEmpty()){ - games = existGames.stream().map(GameDto::new).toList(); + gamesId = existGames.stream().map(Game::getId).toList(); } else { - games = new ArrayList<>(); + gamesId = new ArrayList<>(); } var existPlays = customer.getPlays(); if (existPlays != null && !existPlays.isEmpty()){ - plays = existPlays.stream().map(PlayDto::new).toList(); + playsId = existPlays.stream().map(Play::getId).toList(); } else { - plays = new ArrayList<>(); + playsId = new ArrayList<>(); } } public String getName() { @@ -49,18 +51,18 @@ public class CustomerDto { this.name = name; } - public List getGames() { - return games; + public List getGamesId() { + return gamesId; } - public void setGames(List games){ - this.games = games; + public void setGamesId(List gamesId){ + this.gamesId = gamesId; } - public List getPlays(){ - return plays; + public List getPlaysId(){ + return playsId; } - public void setPlays(List plays){ - this.plays = plays; + public void setPlaysId(List playsId){ + this.playsId = playsId; } public Long getId(){ diff --git a/demo/src/main/java/com/example/demo/dtos/GameDto.java b/demo/src/main/java/com/example/demo/dtos/GameDto.java index 365d65b..459ec55 100644 --- a/demo/src/main/java/com/example/demo/dtos/GameDto.java +++ b/demo/src/main/java/com/example/demo/dtos/GameDto.java @@ -1,6 +1,7 @@ package com.example.demo.dtos; import com.example.demo.models.Game; +import com.example.demo.models.Play; import jakarta.validation.constraints.Min; import jakarta.validation.constraints.NotNull; @@ -15,9 +16,9 @@ public class GameDto { private String description; - private CustomerDto customer; + private Long customerId; - private List plays; + private List playsId; public GameDto(){ @@ -28,20 +29,14 @@ public class GameDto { name = game.getName(); description = game.getDescription(); - var customerExist = game.getCustomer(); - if (customerExist != null){ - customer = new CustomerDto(customerExist); - } - else { - customer = null; - } + customerId = game.getCustomerId(); var playsExist = game.getPlays(); if (playsExist != null && !playsExist.isEmpty()){ - plays = playsExist.stream().map(PlayDto::new).toList(); + playsId = playsExist.stream().map(Play::getId).toList(); } else { - plays = new ArrayList<>(); + playsId = new ArrayList<>(); } } @@ -59,18 +54,18 @@ public class GameDto { this.description = description; } - public CustomerDto getCustomer(){ - return customer; + public Long getCustomerId(){ + return customerId; } - public void setCustomer(CustomerDto customer){ - this.customer = customer; + public void setCustomerId(Long customerId){ + this.customerId = customerId; } - public List getPlays(){ - return plays; + public List getPlaysId(){ + return playsId; } - public void setPlays(List plays){ - this.plays = plays; + public void setPlaysId(List playsId){ + this.playsId = playsId; } public Long getId(){ diff --git a/demo/src/main/java/com/example/demo/dtos/PlayDto.java b/demo/src/main/java/com/example/demo/dtos/PlayDto.java index 07b97d3..d241077 100644 --- a/demo/src/main/java/com/example/demo/dtos/PlayDto.java +++ b/demo/src/main/java/com/example/demo/dtos/PlayDto.java @@ -1,5 +1,6 @@ package com.example.demo.dtos; +import com.example.demo.models.Customer; import com.example.demo.models.Play; import jakarta.validation.constraints.NotNull; @@ -16,9 +17,9 @@ public class PlayDto { private Date date; @NotNull - private GameDto game; + private Long gameId; - private List customers; + private List customersId; public PlayDto(){ @@ -29,20 +30,14 @@ public class PlayDto { description = play.getDescription(); date = play.getDate(); - var existGame = play.getGame(); - if (existGame != null){ - game = new GameDto(existGame); - } - else { - game = null; - } + gameId = play.getGameId(); var existCustomers = play.getCustomers(); if (existCustomers != null && !existCustomers.isEmpty()){ - customers = existCustomers.stream().map(CustomerDto::new).toList(); + customersId = existCustomers.stream().map(Customer::getId).toList(); } else { - customers = new ArrayList<>(); + customersId = new ArrayList<>(); } } @@ -60,18 +55,18 @@ public class PlayDto { this.date = date; } - public GameDto getGame(){ - return game; + public Long getGameId(){ + return gameId; } - public void setGame(GameDto game){ - this.game = game; + public void setGameId(Long gameId){ + this.gameId = gameId; } - public List getCustomers(){ - return customers; + public List getCustomersId(){ + return customersId; } - public void setCustomers(List customers){ - this.customers = customers; + public void setCustomersId(List customersId){ + this.customersId = customersId; } public Long getId(){ diff --git a/demo/src/main/java/com/example/demo/core/error/NotFoundException.java b/demo/src/main/java/com/example/demo/errors/NotFoundException.java similarity index 86% rename from demo/src/main/java/com/example/demo/core/error/NotFoundException.java rename to demo/src/main/java/com/example/demo/errors/NotFoundException.java index eac0fa7..1677326 100644 --- a/demo/src/main/java/com/example/demo/core/error/NotFoundException.java +++ b/demo/src/main/java/com/example/demo/errors/NotFoundException.java @@ -1,4 +1,4 @@ -package com.example.demo.core.error; +package com.example.demo.errors; public class NotFoundException extends RuntimeException { public NotFoundException(Class clazz, Long id) { diff --git a/demo/src/main/java/com/example/demo/models/Customer.java b/demo/src/main/java/com/example/demo/models/Customer.java index a13e561..6f4f7fd 100644 --- a/demo/src/main/java/com/example/demo/models/Customer.java +++ b/demo/src/main/java/com/example/demo/models/Customer.java @@ -18,6 +18,9 @@ public class Customer { private List games = new ArrayList<>(); @ManyToMany + @JoinTable(name="plays_customers", + joinColumns = @JoinColumn(name="customerId", referencedColumnName="id"), + inverseJoinColumns= @JoinColumn(name="playId", referencedColumnName="id") ) @OrderBy("date desc") private List plays = new ArrayList<>(); diff --git a/demo/src/main/java/com/example/demo/models/Game.java b/demo/src/main/java/com/example/demo/models/Game.java index 7492e29..2beadb1 100644 --- a/demo/src/main/java/com/example/demo/models/Game.java +++ b/demo/src/main/java/com/example/demo/models/Game.java @@ -19,7 +19,7 @@ public class Game { private String description; @ManyToOne - @JoinColumn(name = "сustomerId", updatable = false, insertable = false) + @JoinColumn(name = "customerId", updatable = false, insertable = false) private Customer customer; @OneToMany(mappedBy = "game", cascade = CascadeType.ALL, orphanRemoval = true) @@ -75,6 +75,10 @@ public class Game { this.customerId = customer.getId(); } + public long getCustomerId(){ + return customerId; + } + public Set getPlays(){ return plays; } diff --git a/demo/src/main/java/com/example/demo/models/Play.java b/demo/src/main/java/com/example/demo/models/Play.java index fc1df56..6fcd6ca 100644 --- a/demo/src/main/java/com/example/demo/models/Play.java +++ b/demo/src/main/java/com/example/demo/models/Play.java @@ -25,7 +25,10 @@ public class Play { @JoinColumn(name = "gameId", updatable = false, insertable = false) private Game game; - @ManyToMany() + @ManyToMany + @JoinTable(name="plays_customers", + joinColumns = @JoinColumn(name="playId", referencedColumnName="id"), + inverseJoinColumns= @JoinColumn(name="customerId", referencedColumnName="id") ) @OrderBy("name asc") private List customers = new ArrayList<>(); @@ -79,6 +82,10 @@ public class Play { this.gameId = game.getId(); } + public Long getGameId(){ + return gameId; + } + public List getCustomers(){ return customers; } diff --git a/demo/src/main/java/com/example/demo/repositories/CustomerRepository.java b/demo/src/main/java/com/example/demo/repositories/CustomerRepository.java new file mode 100644 index 0000000..5e4e80b --- /dev/null +++ b/demo/src/main/java/com/example/demo/repositories/CustomerRepository.java @@ -0,0 +1,22 @@ +package com.example.demo.repositories; + +import com.example.demo.models.Customer; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; + +import java.util.List; +import java.util.Optional; + +public interface CustomerRepository extends JpaRepository { + @Query("select distinct c from Customer c left join fetch c.plays where c.id = ?1") + Optional findByIdWidthPlays(Long id); + + @Query("select distinct c from Customer c left join fetch c.games where c.id = ?1") + Optional findByIdWidthGames(Long id); + + @Query("select distinct c from Customer c left join fetch c.plays") + List findAllWidthPlays(); + + @Query("select distinct c from Customer c left join fetch c.games") + List findAllWidthGames(); +} diff --git a/demo/src/main/java/com/example/demo/repositories/GameRepository.java b/demo/src/main/java/com/example/demo/repositories/GameRepository.java new file mode 100644 index 0000000..7acc528 --- /dev/null +++ b/demo/src/main/java/com/example/demo/repositories/GameRepository.java @@ -0,0 +1,17 @@ +package com.example.demo.repositories; + +import com.example.demo.models.Game; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.CrudRepository; + +import java.util.List; +import java.util.Optional; + +public interface GameRepository extends CrudRepository { + @Query("select distinct g from Game g left join fetch g.customer left join fetch g.plays where g.id = ?1") + Optional findById(Long id); + + @Query("select distinct g from Game g left join fetch g.customer left join fetch g.plays") + List findAll(); +} diff --git a/demo/src/main/java/com/example/demo/repositories/PlayRepository.java b/demo/src/main/java/com/example/demo/repositories/PlayRepository.java new file mode 100644 index 0000000..dc40c40 --- /dev/null +++ b/demo/src/main/java/com/example/demo/repositories/PlayRepository.java @@ -0,0 +1,18 @@ +package com.example.demo.repositories; + +import com.example.demo.models.Game; +import com.example.demo.models.Play; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.CrudRepository; + +import java.util.List; +import java.util.Optional; + +public interface PlayRepository extends CrudRepository { + @Query("select distinct p from Play p left join fetch p.customers c where p.id = ?1") + Optional findById(Long id); + + @Query("select distinct p from Play p left join fetch p.customers c") + List findAll(); +} diff --git a/demo/src/main/java/com/example/demo/services/CustomerService.java b/demo/src/main/java/com/example/demo/services/CustomerService.java index 11ba442..43a2117 100644 --- a/demo/src/main/java/com/example/demo/services/CustomerService.java +++ b/demo/src/main/java/com/example/demo/services/CustomerService.java @@ -1,56 +1,53 @@ package com.example.demo.services; +import com.example.demo.errors.NotFoundException; import com.example.demo.models.Customer; -import jakarta.persistence.EntityManager; -import jakarta.persistence.EntityNotFoundException; -import jakarta.persistence.PersistenceContext; +import com.example.demo.repositories.CustomerRepository; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import org.springframework.util.StringUtils; import java.util.List; @Service public class CustomerService { - @PersistenceContext - private EntityManager em; + private final CustomerRepository repository; + + public CustomerService(CustomerRepository repository){ + this.repository = repository; + } @Transactional public Customer addCustomer(String name) { - if(!StringUtils.hasText(name)){ - throw new IllegalArgumentException("Empty name"); - } - final Customer customer = new Customer(name); - em.persist(customer); - return customer; + Customer customer = new Customer(name); + return repository.save(customer); } @Transactional public Customer findCustomer(Long id){ - final Customer customer = em.find(Customer.class, id); - if (customer == null){ - throw new EntityNotFoundException(String.format("customer with id [%s] is not found", id)); - } - return customer; + var customer = repository.findByIdWidthPlays(id); + return customer != null ? + repository.findByIdWidthGames(id).orElseThrow(() -> new NotFoundException(Customer.class, id)) : + customer.orElseThrow(() -> new NotFoundException(Customer.class, id)); } @Transactional public List getAllCustomers(){ - return em.createQuery("SELECT u FROM Customer u", Customer.class).getResultList(); + var customers = repository.findAllWidthGames(); + return !customers.isEmpty() ? repository.findAllWidthPlays() : customers; } @Transactional public Customer updateCustomer(Long id, String name){ - final Customer currentCustomer = findCustomer(id); - if(StringUtils.hasText(name)) - currentCustomer.setName(name); - return currentCustomer; + Customer customer = findCustomer(id); + customer.setName(name); + + return repository.save(customer); } @Transactional public Customer deleteCustomer(Long id){ - final Customer currentCustomer = findCustomer(id); - em.remove(currentCustomer); - return currentCustomer; + Customer customer = findCustomer(id); + repository.delete(customer); + return customer; } } diff --git a/demo/src/main/java/com/example/demo/services/GameService.java b/demo/src/main/java/com/example/demo/services/GameService.java index 67dd2b1..8f82f4d 100644 --- a/demo/src/main/java/com/example/demo/services/GameService.java +++ b/demo/src/main/java/com/example/demo/services/GameService.java @@ -1,69 +1,58 @@ package com.example.demo.services; -import com.example.demo.models.Game; +import com.example.demo.errors.NotFoundException; import com.example.demo.models.Customer; +import com.example.demo.models.Game; +import com.example.demo.repositories.GameRepository; import jakarta.persistence.EntityManager; -import jakarta.persistence.EntityNotFoundException; import jakarta.persistence.PersistenceContext; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import org.springframework.util.StringUtils; import java.util.List; @Service public class GameService { - @PersistenceContext - private EntityManager em; - + private final GameRepository repository; + private final CustomerService customerService; - public GameService(CustomerService customerService){ + public GameService(GameRepository repository, CustomerService customerService){ + this.repository = repository; this.customerService = customerService; } @Transactional public Game addGame(Long customerId, String name, String description){ - if(!StringUtils.hasText(name)) { - throw new IllegalArgumentException("Empty name"); - } - final Customer customer = customerService.findCustomer(customerId); - if (customer == null){ - throw new IllegalArgumentException("customerId invalid"); - } - final Game game = new Game(name, description, customer); - em.persist(game); - return game; + Customer customer = customerService.findCustomer(customerId); + Game game = new Game(name, description, customer); + return repository.save(game); } @Transactional public Game findGame(Long id){ - final Game game = em.find(Game.class, id); - if(game == null){ - throw new EntityNotFoundException(String.format("Game with id [%s] is not found", id)); - } - return game; + return repository.findById(id).orElseThrow( + () -> new NotFoundException(Game.class, id)); } @Transactional public List getAllGames(){ - return em.createQuery("SELECT g FROM Game g", Game.class).getResultList(); + return repository.findAll(); } @Transactional public Game updateGame(Long id, String name, String description){ - final Game currentGame = findGame(id); - if(StringUtils.hasText(name)) - currentGame.setName(name); - if(StringUtils.hasText(description)) - currentGame.setDescription(description); - return currentGame; + Game game = findGame(id); + game.setName(name); + game.setDescription(description); + + return repository.save(game); } @Transactional public Game deleteGame(Long id){ - final Game currentGame = findGame(id); - em.remove(currentGame); - return currentGame; + Game game = findGame(id); + repository.delete(game); + return game; } } diff --git a/demo/src/main/java/com/example/demo/services/PlayService.java b/demo/src/main/java/com/example/demo/services/PlayService.java index d7bdfec..9931ffd 100644 --- a/demo/src/main/java/com/example/demo/services/PlayService.java +++ b/demo/src/main/java/com/example/demo/services/PlayService.java @@ -1,81 +1,74 @@ package com.example.demo.services; +import com.example.demo.errors.NotFoundException; +import com.example.demo.models.Customer; import com.example.demo.models.Game; import com.example.demo.models.Play; -import com.example.demo.models.Customer; -import jakarta.persistence.EntityManager; -import jakarta.persistence.EntityNotFoundException; -import jakarta.persistence.PersistenceContext; +import com.example.demo.repositories.PlayRepository; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import org.springframework.util.StringUtils; import java.util.Date; import java.util.List; @Service public class PlayService { - @PersistenceContext - private EntityManager em; + private final PlayRepository repository; private final GameService gameService; private final CustomerService customerService; - public PlayService(GameService gameService, CustomerService customerService){ + public PlayService(PlayRepository repository, GameService gameService, CustomerService customerService){ + this.repository = repository; this.gameService = gameService; this.customerService = customerService; } @Transactional public Play addPlay(Long gameId, Date date, String description){ - final Game game = gameService.findGame(gameId); + Game game = gameService.findGame(gameId); - if (game == null){ - throw new IllegalArgumentException("gameId invalid"); - } - - final Play Play = new Play(game, date, description); - em.persist(Play); - return Play; + Play play = new Play(game, date, description); + return repository.save(play); } @Transactional public Play findPlay(Long id){ - final Play Play = em.find(Play.class, id); - if (Play == null){ - throw new EntityNotFoundException(String.format("Play with id [%s] is not found", id)); - } - return Play; + return repository.findById(id).orElseThrow( + () -> new NotFoundException(Play.class, id)); } @Transactional public List getAllPlays(){ - return em.createQuery("SELECT p FROM Play p", Play.class).getResultList(); + return repository.findAll(); } @Transactional public Play updatePlay(Long id, Date date, String description){ - final Play currentPlay = findPlay(id); + Play play = findPlay(id); - if(StringUtils.hasText(description)) - currentPlay.setDescription(description); - if(date != null) - currentPlay.setDate(date); - return currentPlay; + play.setDate(date); + play.setDescription(description); + + return repository.save(play); } @Transactional public Play deletePlay(Long id){ - final Play currentPlay = findPlay(id); - em.remove(currentPlay); - return currentPlay; + Play play = findPlay(id); + repository.delete(play); + return play; } @Transactional public boolean addCustomer(Long id, Long customerId){ - final Play currentPlay = findPlay(id); + final Play play = findPlay(id); final Customer customer = customerService.findCustomer(customerId); - return customer.addPlay(currentPlay); + if (customer.addPlay(play)){ + repository.save(play); + return true; + } + return false; } } diff --git a/demo/src/main/resources/application.properties b/demo/src/main/resources/application.properties index 23eb036..7101a03 100644 --- a/demo/src/main/resources/application.properties +++ b/demo/src/main/resources/application.properties @@ -9,3 +9,6 @@ spring.jpa.hibernate.ddl-auto=update spring.h2.console.enabled=true spring.h2.console.settings.trace=false spring.h2.console.settings.web-allow-others=false + +spring.jpa.show-sql=true +spring.jpa.properties.hibernate.format_sql=true