Hibernate和NonUniqueObjectException

时间:2010-08-22 22:27:09

标签: java hibernate exception unique-constraint

我有一个实体,其中包含两个具有@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)不是唯一约束!!

我该怎么办?

提前感谢。

1 个答案:

答案 0 :(得分:16)

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

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

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

重申 - 这个异常与数据库约束没什么关系,它是关于Hibernate保护其内部内存状态的一致性。