我发现很多帖子都解释说应该始终覆盖 NHibernate 实体类上的 Equals/GetHashCode。如果我不使用 Sets,这真的有必要吗?
我根本找不到显示缺少 Equals/GetHashCode 会导致意外和错误行为的示例。没有它们,一切似乎都可以完美运行。这真的很奇怪,每个人都说这是必要的,但没有人能提供一个样本来说明为什么需要这样做。
我发现很多帖子都解释说应该始终覆盖 NHibernate 实体类上的 Equals/GetHashCode。如果我不使用 Sets,这真的有必要吗?
我根本找不到显示缺少 Equals/GetHashCode 会导致意外和错误行为的示例。没有它们,一切似乎都可以完美运行。这真的很奇怪,每个人都说这是必要的,但没有人能提供一个样本来说明为什么需要这样做。
最近有一个关于NHibernate 执行 select N+1 的问题,即使fetch
已指定。问题在于缺少Equals
/GetHashCode
实施。
答案链接到另一个类似的问题。
这是关于背后推理/覆盖的另一个问题。Equals
GetHashCode
具有三元关系的休眠 n+1。
尽管 HQL 获取 NHibernate,但仍需要三元 Nhibernate 生成代理中的中间实体
:重写 Equals 和 GetHashCode
的原因 为什么 Equals 和 GetHashCode 对 NHibernate 如此重要
为什么在重写 Equals 方法时重写 GetHashCode 很重要?
编辑
您不需要一直覆盖它们。如果您使用复合键、具有分离实体的多个会话或无状态会话,则可能有必要。
如果您只使用单个会话,NHibernate 使用身份映射将实体存储到第一级缓存。在这种情况下,实体比较是通过比较 id 来完成的。
在上述情况下(分离实体、无状态会话),NHibernate 比较实际实体,而不是它们的 id。默认情况下,Object.Equals
确实引用相等。因此,如果两个对象指向完全相同的实例,则它们是相等的。您可能有两个具有相同身份的实例,但Object.Equals
会false
为它们返回。这与Entity
定义相反:
不是由其属性定义的对象,而是由连续性及其身份定义的对象。
JBoss Hibernate wiki 有一个很好的解释,Equals
并且HashCode
很少有代码示例。
事实上,只有极少数情况会导致副作用。但如果你得到它们,它们就会非常微妙。除了复合主键和字典键,它们总是需要正确的 Equals / GetHashCode 实现。
NH 只关心在内存中实例化一个实体一次,所以默认的引用比较应该可以工作……如果没有延迟加载的话。
如果不覆盖 Equals,则在处理代理时会遇到问题。总是有两个实例:代理和真实实体。它们都代表同一个实体。只有使用正确实现的 Equals 方法,它才会被视为相同。