我有@Entity的Recipe.java对象:
...
@OneToMany(cascade = CascadeType.ALL)
private List<Category> category;
...
然后使用@Entity:
的Category.java对象...
@OneToOne(cascade = CascadeType.ALL)
private Name name;
...
让我们说db看起来像这样(recipe_category表):
然后执行以下代码(我只想在配方中添加一个类别):
...
Recipe recipe = recipeRepository.findOne(recipeId);
Category ctg = categoryRepository.findOne(categoryId); // id=1
List<Category> categories = recipe.getCategory();
categories.add(ctg);
recipe.setCategory(categories);
recipeRepository.save(recipe);
...
在recipeRepository.save(recipe)
我收到以下错误:
com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '1' for key 'UK_2n5xttsxwbyc6x67l0x8phfwn'
那么这个问题的解决方案是什么?
更新:
配方表结构如下所示:
类别表结构如下所示:
所以问题似乎发生了,因为当recipe.setCategory(categories);
被触发时,它会尝试将ctg
保存到数据库,但它已经存在。我想要的不是将它保存到db(因为&#39;类别&#39;表中已经存在),而是在recipe_category
表中添加新行。
也许它必须用cascade做点什么?
答案 0 :(得分:1)
你的关系不是一对多的。您希望每个食谱都有多个类别。我想你也希望每个类别与多个食谱相关联。这是一种多对多的关系。您需要使用@ManyToMany
注释来配置实体。
另请注意,Hibernate关系始终是单向的。当您在@ManyToMany
课程中添加Recipe
注释时,您可以访问与给定食谱相关联的类别。要访问反向关系,要获取给定类别的配方,您还需要向@ManyToMany
类添加带Category
注释的相应属性。
我猜您使用了hbm2ddl或类似的方法来自动创建表,因为表是为一对多关系创建的,所以会出错。更具体地说,在单向一对多关系中,连接表中的逆外键列(category_id
表中的recipe_category
)具有在其上定义的唯一约束。因此,使用该表模式,您无法将类别与多个配方相关联。
这样的事情应该有效:
// Recipe
@ManyToMany(cascade=CascadeType.ALL)
@JoinTable(name="category_map", )
private List<Category> categories = new ArrayList<> ();
和
// Category
@ManyToMany(cascade=CascadeType.ALL, mappedBy="categories")
private Set<Recipe> recipes;
答案 1 :(得分:0)
Recipe recipe = recipeRepository.findOne(recipeId);
Category ctg = categoryRepository.findOne(categoryId); // id=1
List<Category> categories = recipe.getCategory();
categories.add(ctg);
recipe.setCategory(categories);
recipeRepository.save(recipe);
//categories.clear();