我有两个实体:膳食和产品。每顿饭都有几个产品,每种产品都可以存在于每顿饭中,因此关系为@ManyToMany,其中Meal是父母。
我想用产品保存Meal,但问题是DB中的产品是重复的。
如何归档一个案例,如果产品存在于数据库中,则不保存它,而只与现有的连接?
(应用程序解析来自外部API(Nutritionix(的产品,将它们收集在一起,然后单独保存产品,并将Meal作为计算数据的Parent(
我试着插入if(!productService.ifExists(food.getFoodName())) productService.save(food);
进入保存功能并删除cascadeType,但当产品已经存在时,我会得到一个错误:
org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing:
@Entity
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@JsonBackReference
@ManyToMany(mappedBy = "foodList")
private Set<Meal> meals = new HashSet<>();
@Column(unique = false, nullable = false)
private String foodName;
...}
@Entity
public class Meal {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@JsonManagedReference
@ManyToMany(cascade ={ CascadeType.PERSIST, CascadeType.MERGE})
private Set<Product> foodList = new HashSet<>();
@NaturalId
@Column(unique = true, nullable = false)
private String mealName;
...}
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());
}
return mealService.save(newMeal);
}
首先,可以将成分称为Ingredient
s,而不是Product
s。
其次,问题可能在于我们看不到的方法parseFoodToProduct(foodList);
的代码,与指令有关
@JsonManagedReference
@ManyToMany(cascade ={ CascadeType.PERSIST, CascadeType.MERGE})
private Set<Product> foodList = new HashSet<>();
如果在parseFoodToProduct(foodList);
中创建新的Product
(xxx = new Product(...)
(,而不是从数据库中加载它们,这肯定会适得其反。
去掉CascadeType
,始终单独创建/检索/更新/存储Product
,这样它们就完全独立于使用/引用它们的位置。