【问题标题】:Hibernate and NonUniqueObjectExceptionHibernate 和 NonUniqueObjectException
【发布时间】:2011-04-02 09:42:39
【问题描述】:

我有一个实体,其中包含两个具有 @ManyToOne 关系的其他实体。

@Entity
public class A extends Serializable{

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

    @ManyToOne
    @Cascade(CascadeType.SAVE_UPDATE)
    private B b;

    @ManyToOne
    @Cascade(CascadeType.SAVE_UPDATE)
    private C c;

}

如果我尝试保存具有另一个 A 记录的“B_ID”和“C_ID”的 A 实例,我会得到异常:

org.hibernate.NonUniqueObjectException:具有相同标识符值的不同对象已与会话关联

例如:

A table
|   ID  |   B_ID    |   C_ID    |
|    1  |      1    |   null    |    // this works
|    2  |   null    |      1    |    // this works
|    3  |      1    |      x    |    // this throws the exception
|    4  |      x    |      1    |    // this throws the exception

x=any value of existent B/C_ID 

B_ID 和 C_ID 在我的模型中不是唯一的,并且 (B_ID + C_ID) 不是唯一约束!!

我能做什么?

提前致谢。

【问题讨论】:

    标签: java hibernate exception unique-constraint


    【解决方案1】:

    Hibernate 在这里并没有抱怨数据库的唯一性,它抱怨当前的Session 已经包含一个与您要保存的新对象具有相同 ID 的对象。它不允许这样做——Hibernate 有一个严格的要求,即给定 ID 不能由单个会话范围内的两个不同对象表示。

    在某些时候,您的应用程序已保存或加载了具有相同 ID 的实体,并且该对象已在会话中“注册”。在这种特定情况下,很难说出它在抱怨哪个 ID,因为异常文本不清楚。尝试暂时删除级联指令,看看它是否仍然发生,尝试缩小范围。

    如有必要,您可以强制会话“忘记”给定 ID 的任何现有对象(在 Hibernate API 中使用 Session.evict(),或在 JPA 2.0 API 中使用 EntityManager.detach()),但这不是很优雅解决方案。

    重申一下 - 此异常与数据库约束无关,它是关于 Hibernate 保护其内部内存状态的一致性。

    【讨论】:

    • 谢谢,我从 db 加载的唯一东西是 B 和 C,我在 A 对象中使用它们。但是 B 和 C 有 CascadeType.SAVE_UPDATE,所以它们不会再次保存,而只是更新...我希望...
    • 问题在开始时也会出现,当会话是新的时。
    • 删除级联指令效果很好,但是......为什么?如果没有“Cascade.SAVE_UPDATE”,休眠应该尝试重新保存已经存在于 db 中的“A”和“B”并抛出异常,但它可以代替......为什么?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多