7

我发现很多帖子都解释说应该始终覆盖 NHibernate 实体类上的 Equals/GetHashCode。如果我不使用 Sets,这真的有必要吗?

我根本找不到显示缺少 Equals/GetHashCode 会导致意外和错误行为的示例。没有它们,一切似乎都可以完美运行。这真的很奇怪,每个人都说这是必要的,但没有人能提供一个样本来说明为什么需要这样做。

4

2 回答 2

11

最近有一个关于NHibernate 执行 select N+1 的问题,即使fetch已指定。问题在于缺少Equals/GetHashCode实施。

答案链接到另一个类似的问题

这是关于背后推理/覆盖的另一个问题。EqualsGetHashCode

具有三元关系的休眠 n+1。
尽管 HQL 获取 NHibernate,但仍需要三元 Nhibernate 生成代理中的中间实体
:重写 Equals 和 GetHashCode
的原因 为什么 Equals 和 GetHashCode 对 NHibernate 如此重要
为什么在重写 Equals 方法时重写 GetHashCode 很重要?


编辑

您不需要一直覆盖它们。如果您使用复合键、具有分离实体的多个会话或无状态会话,则可能有必要。

如果您只使用单个会话,NHibernate 使用身份映射将实体存储到第一级缓存。在这种情况下,实体比较是通过比较 id 来完成的。

在上述情况下(分离实体、无状态会话),NHibernate 比较实际实体,而不是它们的 id。默认情况下,Object.Equals确实引用相等。因此,如果两个对象指向完全相同的实例,则它们是相等的。您可能有两个具有相同身份的实例,但Object.Equalsfalse为它们返回。这与Entity 定义相反:

不是由其属性定义的对象,而是由连续性及其身份定义的对象。

JBoss Hibernate wiki 有一个很好的解释Equals并且HashCode很少有代码示例。

于 2012-07-12T07:41:32.153 回答
4

事实上,只有极少数情况会导致副作用。但如果你得到它们,它们就会非常微妙。除了复合主键和字典键,它们总是需要正确的 Equals / GetHashCode 实现。

NH 只关心在内存中实例化一个实体一次,所以默认的引用比较应该可以工作……如果没有延迟加载的话。

如果不覆盖 Equals,则在处理代理时会遇到问题。总是有两个实例:代理和真实实体。它们都代表同一个实体。只有使用正确实现的 Equals 方法,它才会被视为相同。

于 2012-07-12T10:44:04.180 回答