我的equals()和hashcode()方法已被正确覆盖。但当 我正在保存相同的对象,它们出现在数据库中。我怎么解决这个问题?我想在数据库中拥有唯一的元素集。 谢谢。
这是映射文件:
<hibernate-mapping>
<class name="vertical.model.filter.Filter" table="FILTER">
<id name="id" type="long">
<generator class="native"/>
</id>
<discriminator column="TYPE" type="string"/>
<subclass name="vertical.impl.filter.AbstractFilter" abstract="true">
<set name="options" table="FILTER_OPTION" cascade="all">
<key column="FILTER_ID"/>
<many-to-many column="OPTION_ID" class="vertical.model.filter.FilterOption"/>
</set>
<subclass name="vertical.impl.services.filter.GrfFilter"
discriminator-value="rabota">
</subclass>
</subclass>
</class>
</hibernate-mapping>
答案 0 :(得分:1)
这是一个经典的问题,没有理论上的解决方案,但有实际的解决方法。
让我从article;
开始问题源于虚拟机(VM)中的对象标识与数据库中的对象标识之间的差异。在VM中,您没有获得对象的ID;你只需要直接引用该对象。在幕后,VM确实分配了一个8字节的ID,这是对对象的真正引用。在数据库中持久保存对象时会出现问题。假设您创建一个Person对象并将其保存到数据库(person1)。您在代码中的其他位置读取Person数据并实例化一个新的Person对象(person2)。现在,内存中有两个对象映射到数据库中的同一行。对象引用只能指向一个或另一个,但我们需要一种方法来表明这些实际上是同一个实体。这就是对象身份的来源。
您应该做的很简单,根据实体的业务功能覆盖equals()
和hashcode()
。
以下是来自hibernate论坛article;
的建议解决方案分隔对象ID和业务键 为避免此问题,我们建议使用持久化类的“semi”-unique属性来实现equals()(和hashCode())。基本上,您应该将您的数据库标识符视为根本没有业务含义(请记住,无论如何都建议使用代理标识符属性和自动生成的值)。数据库标识符属性应该只是一个对象标识符,基本上只应由Hibernate使用。当然,您也可以使用数据库标识符作为方便的只读句柄,例如在Web应用程序中构建链接。