@ManyToMany повторяющиеся записи - PullRequest
0 голосов
/ 31 марта 2020

У меня проблема с сохранением. У меня есть класс еды, в котором список продуктов. В классе Product есть список Meals - отношение @ManyToMany.

Когда я пытаюсь сохранить его, компилятор хочет сохранить каждый продукт, но затем продукты дублируются в моей БД. Как я могу указать, что продукты уже есть?

Вот мой код

@Entity
public class Meal {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @JsonManagedReference
    @ManyToMany(cascade = {
            CascadeType.MERGE
    })
    private List<Product> foodList = new ArrayList<>();

    @NaturalId
    @Column(unique = true, nullable = false)
    private String mealName;

    private Integer servingWeightGrams = 0;
    private Integer servingQty = 0;
    private Double nfCalories = 0d;
    private Double nfTotalFat = 0d;
    ...

@Entity
public class Product {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @JsonBackReference
    @ManyToMany(mappedBy = "foodList")
    private List<Meal> meals = new ArrayList<>();

    @Column(unique = false, nullable = false)
    private String foodName;
    ...
@Service
public class MealManager {

    MealService mealService;
    ProductService productService;

    @Autowired
    public MealManager(MealService mealService, ProductService productService)
    {
        this.mealService = mealService;
        this.productService = productService;
    }

    public Meal saveMeal(List<Food> foodList, String mealName){

        Meal newMeal = new Meal();
        newMeal.setMealName(mealName);

        List<Product> productList = parseFoodToProduct(foodList);

        productList.stream().forEach(y -> newMeal.getFoodList().add(y));

        for(Product food : productList) {

            newMeal.setNfCalories(newMeal.getNfCalories() + food.getNfCalories());
            newMeal.setNfCholesterol(newMeal.getNfCholesterol() + food.getNfCholesterol());
            newMeal.setNfDietaryFiber(newMeal.getNfDietaryFiber() + food.getNfDietaryFiber());
            newMeal.setNfP(newMeal.getNfP() + food.getNfP());
            newMeal.setNfPotassium(newMeal.getNfPotassium() + food.getNfPotassium());
            newMeal.setNfProtein(newMeal.getNfProtein() + food.getNfProtein());
            newMeal.setNfSaturatedFat(newMeal.getNfSaturatedFat() + food.getNfSaturatedFat());
            newMeal.setNfSodium(newMeal.getNfSodium() + food.getNfSodium());
            newMeal.setNfSugars(newMeal.getNfSugars() + food.getNfSugars());
            newMeal.setNfTotalCarbohydrate(newMeal.getNfTotalCarbohydrate() + food.getNfTotalCarbohydrate());
            newMeal.setNfTotalFat(newMeal.getNfTotalFat() + food.getNfTotalFat());
            newMeal.setServingWeightGrams(newMeal.getServingWeightGrams() + food.getServingWeightGrams());

           /*if(! productService.ifExists(food.getFoodName())) */  productService.save(food);
        }

        return mealService.save(newMeal);
    }

1 Ответ

0 голосов
/ 31 марта 2020

Вам, вероятно, не нужно вызывать productService.save(food) в конце вашего для l oop в MealManager.

Вы можете попробовать добавить некоторые служебные методы в класс Meal, чтобы сохраняйте отношения в синхронизации c, как описано в этой статье .

Итак, в вашем классе Meal вы можете добавить метод, подобный

public void addProduct(Product product) {
   foodList.add(product);
   product.getMeals().add(this);
}

и вызовите этот метод внутри для l oop in MealManager вместо простого вызова newMeal.getFoodList().add(y).

Поскольку для ManyToMany определено CascadeType.MERGE, отношения будут синхронизированы в обе сущности.

Другие наблюдения:

  • Я не вижу, что делает метод parseFoodToProduct, но, предполагая, что он получает необходимые продукты из БД, вы должны отметить saveMeal метод как @Transactional

  • Вы проходите 2 раза по productList в saveMeal ... один раз с stream().forEach() и один раз с расширенным для. .. Я бы оставил в этом контексте только расширенное значение для

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...