fix(server): fix duplicate Ingredient present in each recipe
An issue where multiple instances of a uniquely named Ingredient are stored in the database. This is patched by checking server-side whether an ingredient exists before persisting it. This now correctly implements the Many-to-Many reference.
This commit is contained in:
parent
2d1df8fc11
commit
d497ed108e
2 changed files with 21 additions and 15 deletions
|
|
@ -22,6 +22,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import server.database.IngredientRepository;
|
||||||
import server.database.RecipeIngredientRepository;
|
import server.database.RecipeIngredientRepository;
|
||||||
import server.database.RecipeRepository;
|
import server.database.RecipeRepository;
|
||||||
|
|
||||||
|
|
@ -34,16 +35,16 @@ public class RecipeController {
|
||||||
private final RecipeRepository recipeRepository; // JPA repository used in this controller
|
private final RecipeRepository recipeRepository; // JPA repository used in this controller
|
||||||
private final SimpMessagingTemplate messagingTemplate;
|
private final SimpMessagingTemplate messagingTemplate;
|
||||||
private final RecipeIngredientRepository recipeIngredientRepository;
|
private final RecipeIngredientRepository recipeIngredientRepository;
|
||||||
private final IngredientController ingredientController;
|
private final IngredientRepository ingredientRepository;
|
||||||
|
|
||||||
public RecipeController(RecipeRepository recipeRepository,
|
public RecipeController(RecipeRepository recipeRepository,
|
||||||
SimpMessagingTemplate messagingTemplate,
|
SimpMessagingTemplate messagingTemplate,
|
||||||
IngredientController ingredientController,
|
IngredientRepository ingredientRepository,
|
||||||
RecipeIngredientRepository recipeIngredientRepository) {
|
RecipeIngredientRepository recipeIngredientRepository) {
|
||||||
this.recipeRepository = recipeRepository;
|
this.recipeRepository = recipeRepository;
|
||||||
this.messagingTemplate = messagingTemplate;
|
this.messagingTemplate = messagingTemplate;
|
||||||
this.recipeIngredientRepository = recipeIngredientRepository;
|
this.recipeIngredientRepository = recipeIngredientRepository;
|
||||||
this.ingredientController = ingredientController;
|
this.ingredientRepository = ingredientRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -80,7 +81,19 @@ public class RecipeController {
|
||||||
|
|
||||||
return ResponseEntity.ok(recipeRepository.findAll());
|
return ResponseEntity.ok(recipeRepository.findAll());
|
||||||
}
|
}
|
||||||
|
private Recipe saveRecipeAndDependencies(Recipe recipe) {
|
||||||
|
recipe.getIngredients()
|
||||||
|
.forEach(recipeIngredient ->
|
||||||
|
recipeIngredient.setIngredient(
|
||||||
|
ingredientRepository
|
||||||
|
.findByName(recipeIngredient.getIngredient().name)
|
||||||
|
.orElseGet(() -> ingredientRepository.save(recipeIngredient.getIngredient())
|
||||||
|
))
|
||||||
|
);
|
||||||
|
recipeIngredientRepository.saveAll(recipe.getIngredients());
|
||||||
|
Recipe saved = recipeRepository.save(recipe);
|
||||||
|
return saved;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Mapping for <code>POST /recipe/{id}</code>.
|
* Mapping for <code>POST /recipe/{id}</code>.
|
||||||
* Also creates the ingredient elements if they do not exist.
|
* Also creates the ingredient elements if they do not exist.
|
||||||
|
|
@ -94,11 +107,7 @@ public class RecipeController {
|
||||||
if (!recipeRepository.existsById(id)) {
|
if (!recipeRepository.existsById(id)) {
|
||||||
return ResponseEntity.badRequest().build();
|
return ResponseEntity.badRequest().build();
|
||||||
}
|
}
|
||||||
recipe.getIngredients().stream()
|
Recipe saved = saveRecipeAndDependencies(recipe);
|
||||||
.map(recipeIngredient -> recipeIngredient.ingredient)
|
|
||||||
.forEach(ingredientController::createIngredient);
|
|
||||||
recipeIngredientRepository.saveAll(recipe.getIngredients());
|
|
||||||
Recipe saved = recipeRepository.save(recipe);
|
|
||||||
messagingTemplate.convertAndSend(Topics.RECIPES, new UpdateRecipeMessage(saved));
|
messagingTemplate.convertAndSend(Topics.RECIPES, new UpdateRecipeMessage(saved));
|
||||||
|
|
||||||
return ResponseEntity.ok(saved);
|
return ResponseEntity.ok(saved);
|
||||||
|
|
@ -128,12 +137,7 @@ public class RecipeController {
|
||||||
if (recipeRepository.exists(Example.of(example))) {
|
if (recipeRepository.exists(Example.of(example))) {
|
||||||
return ResponseEntity.badRequest().build();
|
return ResponseEntity.badRequest().build();
|
||||||
}
|
}
|
||||||
// FIXME reduce code duplication
|
Recipe saved = saveRecipeAndDependencies(recipe);
|
||||||
recipe.getIngredients().stream()
|
|
||||||
.map(recipeIngredient -> recipeIngredient.ingredient)
|
|
||||||
.forEach(ingredientController::createIngredient);
|
|
||||||
recipeIngredientRepository.saveAll(recipe.getIngredients());
|
|
||||||
Recipe saved = recipeRepository.save(recipe);
|
|
||||||
messagingTemplate.convertAndSend(Topics.RECIPES, new CreateRecipeMessage(saved));
|
messagingTemplate.convertAndSend(Topics.RECIPES, new CreateRecipeMessage(saved));
|
||||||
|
|
||||||
return ResponseEntity.ok(saved);
|
return ResponseEntity.ok(saved);
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,11 @@ import org.springframework.data.domain.Pageable;
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
public interface IngredientRepository extends JpaRepository<Ingredient, Long> {
|
public interface IngredientRepository extends JpaRepository<Ingredient, Long> {
|
||||||
List<Ingredient> findAllByOrderByNameAsc();
|
List<Ingredient> findAllByOrderByNameAsc();
|
||||||
Page<Ingredient> findAllByOrderByNameAsc(Pageable pageable);
|
Page<Ingredient> findAllByOrderByNameAsc(Pageable pageable);
|
||||||
|
Optional<Ingredient> findByName(String name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue