Jakarta Persistence 3.0,第4.12节写道:
相同抽象模式类型的两个实体当且仅当它们具有相同的主键值时相等。
我看不出为什么Java代码的行为应该有所不同。
If the entity class is in a so called "transient" state, i.e. it's not yet persisted and it has no identifier, then the hashCode/equals methods can not return a value, they ought to blow up, ideally implicitly with a NullPointerException when the method attempts to traverse the ID. Either way, this will effectively stop application code from putting a non-managed entity into a hash-based data structure. In fact, why not go one step further and blow up if the class and identifier are equal, but other important attributes such as the version are unequal (IllegalStateException)! Fail-fast in a deterministic way is always the preferred option.
警告:也要记录下爆发行为。文档本身很重要,但它也希望能够阻止初级开发人员在未来对您的代码做一些愚蠢的事情(他们倾向于压制发生NullPointerException的地方,他们最不关心的是副作用,lol)。
哦,总是使用getClass()而不是instanceof。equals方法要求对称性。如果b等于a,那么a必须等于b。对于子类,instanceof打破了这种关系(a不是b的实例)。
尽管我个人总是使用getClass(),即使在实现非实体类(类型是状态,所以子类添加状态,即使子类是空的或只包含行为),只有当类是final时,instanceof才会很好。但实体类必须不是最终的(§2.1),所以我们真的别无选择。
Some folks may not like getClass(), because of the persistence provider's proxy wrapping the object. This might have been a problem in the past, but it really shouldn't be. A provider not returning different proxy classes for different entities, well, I'd say that's not a very smart provider lol. Generally, we shouldn't solve a problem until there is a problem. And, it seems like Hibernate's own documentation doesn't even see it worthwhile mentioning. In fact, they elegantly use getClass() in their own examples (see this).
Lastly, if one has an entity subclass that is an entity, and the inheritance mapping strategy used is not the default ("single table"), but configured to be a "joined subtype", then the primary key in that subclass table will be the same as the superclass table. If the mapping strategy is "table per concrete class", then the primary key may be the same as in the superclass. An entity subclass is very likely to be adding state and therefore just as likely to be logically a different thing. But an equals implementation using instanceof can not necessarily and secondarily rely on the ID only, as we saw may be the same for different entities.
在我看来,instanceof在非final Java类中根本没有位置。对于持久实体来说尤其如此。