【问题标题】:Hibernate collection update foiled by unique indexHibernate 集合更新被唯一索引挫败
【发布时间】:2014-10-10 01:37:48
【问题描述】:

我正在尝试将子对象从一个父对象移动到另一个父对象,该对象位于由 Hibernate 控制的数据库中。我在 Hibernate 通过 @OneToMany 注释创建和控制的表上遇到错误。希望有人知道解决此问题的方法。

我有两个对象,一个包含另一个的列表。让我们称它们为犬舍和狗。我正在做的是将Dog 从一个Kennel 移动到另一个Kennel

    Dog dog = dogService.getDog(dogId);
    Kennel oldKennel = dog.getKennel();

    if (oldKennel.getDogs().contains(dog)) {
        oldKennel.getDogs().remove(dog);
    }

    Kennel newKennel = kennelService.getKennel(newKennelId);
    newKennel.getDogs().add(dog);
    dog.setKennel(newKennel);

涉及三个表:

-- Table is mapped to Kennel object    
TABLE kennels (kennel_id int)
-- Table is a join table controlled by Hibernate
TABLE kennels_dogs (kennels_kennel_id int, dogs_dog_id int)
-- Table is mapped to Dog object
TABLE dogs (dog_id int)

我得到的具体错误是在连接表kennels_dogs

java.sql.BatchUpdateException: Duplicate entry '14' for key 'dogs_dog_id'

但文件中只有一条具有该 ID 的记录 - 我正在尝试更新的那条记录。 Hibernate 似乎在做的是尝试INSERTkennels_dogs 表中使用新值DELETES旧记录之前的记录。

例如,假设 id=14 的 Dog 在 id=12 的 Kennel 中。我们想将 Dog 移动到 id=47 的犬舍。手动,您可以使用以下命令执行此操作:

DELETE FROM kennels_dogs WHERE kennels_kennel_id=12 AND dogs_dog_id=12
INSERT INTO kennels_dogs (kennels_kennel_id, dogs_dog_id) VALUES (47, 12)

Hibernate 所做的是以相反的顺序执行这些操作:

INSERT INTO kennels_dogs (kennels_kennel_id, dogs_dog_id) VALUES (47, 12)
DELETE FROM kennels_dogs WHERE kennels_kennel_id=12 AND dogs_dog_id=12

INSERT 失败,因为 dogs_dog_id 字段上的唯一索引 - 表中已经存在 dogs_dog_id = 12 的记录。

似乎显而易见的解决方案可能是删除唯一索引,但不知道它为什么存在,我很犹豫是否要删除它(从逻辑上讲,这是正确的 - Dog 只能在一个地方时间。)

谁有解决这个问题的绝妙方法?

【问题讨论】:

    标签: java mysql sql hibernate


    【解决方案1】:

    你有一个 kennels_dogs 连接表对我来说似乎很奇怪。对于@OneToMany,这应该不是必需的。根据休眠文档:

    6.2.5。一对多关联

    一对多关联通过一个外键链接两个类的表,没有 干预收集表。

    我会确保你在你的犬舍类的狗收藏上标注了@OneToMany(mappedBy = "dog"),以及@ManyToOne @JoinColumn(name = "kennel_id", nullable = false) 在您的 Dog 类上添加注释。

    【讨论】:

    • 是的,没有充分的理由让该表存在,因为这是一对多的关系。许多人多年来一直致力于此设计,我敢肯定这是较早时代的产物。
    • 我将其标记为正确,因为它实际上是正确的答案 - 此架构中不应包含连接表。然而,我实际解决这个问题的方式完全不同,而且非常愚蠢和特殊,希望没有其他人需要解决同样的问题。它涉及控制器级别的事务和糟糕的屏幕设计。就像我说的希望没有其他人会遇到它。 :(
    猜你喜欢
    • 2019-09-30
    • 2011-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-19
    • 2014-01-09
    相关资源
    最近更新 更多