【问题标题】:Hibernate saving to db "Duplicate entry '1' for key 'UK_2n5xttsxwbyc6x67l0x8phfwn'"休眠保存到 db “键 'UK_2n5xttsxwbyc6x67l0x8phfwn' 的重复条目 '1'”
【发布时间】:2017-04-22 21:47:26
【问题描述】:

我有带有@Entity 的Recipe.java 对象:

...  
@OneToMany(cascade = CascadeType.ALL)
private List<Category> category;  
...  

然后是带有@Entity 的Category.java 对象:

...  
@OneToOne(cascade = CascadeType.ALL)  
private Name name;  
...

假设数据库看起来像这样(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(因为它已经存在于“类别”表中),而是在 recipe_category 表中添加一个新行。

也许它与级联有关?

【问题讨论】:

  • 我认为这是由于滥用@OneToMany,这个答案可能会有所帮助:stackoverflow.com/a/15802642/7624937
  • 如何创建表?你能发布表结构、创建脚本或者至少是异常中提到的键的定义吗?
  • @infiniteRefactor 我已经用有关表结构的一些细节更新了这个问题。所以问题不在于“创建”过程,而是当我想将现有类别添加到配方时。

标签: java mysql spring hibernate


【解决方案1】:

你们的关系不是一对多的。您希望每个食谱都有多个类别。我猜您还希望每个类别都与多个食谱相关联。这是一个多对多的关系。您需要使用 @ManyToMany 注释来配置您的实体。

还要注意,Hibernate 关系始终是单向的。当您将 @ManyToMany 注释放在 Recipe 类中时,您可以访问与给定配方关联的类别。为了访问反向关系,要获取给定类别的食谱,您还需要将带有 @ManyToMany 注释的适当属性添加到 Category 类。

我猜您使用 hbm2ddl 或类似方法来自动创建表,并且由于表是为一对多关系创建的,因此您会收到错误。更具体地说,在单向一对多关系中,连接表中的反向外键列(recipe_category 表中的category_id)具有对其定义的唯一约束。因此,使用该表架构,您不能将一个类别与多个配方相关联。

这样的事情应该可以工作:

// 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;    

【讨论】:

  • 感谢您的解决方案和解释。它有效。
  • 谢谢,一个小时也遇到了同样的问题。忘记了其他关系也被许多实体使用
【解决方案2】:
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();

【讨论】:

    猜你喜欢
    • 2021-12-02
    • 1970-01-01
    • 2014-04-13
    • 1970-01-01
    • 1970-01-01
    • 2013-03-25
    • 2016-11-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多