При предоставлении реализации #equals
для UDT в Java одним из условий является то, что переданный объект аргумента должен быть экземпляром текущего класса, в противном случае мы быстро return false
ошибемся, см. Эффективная Java (EJ2). Однако при использовании Hibernate 4 мы можем получить экземпляры прокси-сервера javassist из-за ленивой загрузки, когда это условие #equals
не сработает. Что было бы лучшим выбором, чтобы преодолеть это? Несколько вариантов, о которых я могу думать, это:
- расширить реализацию
equals
, чтобы учесть случай прокси. Минусы: плата за ремонтопригодность, аппаратная зависимость от прокси-инфраструктуры Hibernate, хакерские модели, модели сущностей или доменов не должны зависеть от используемого ORM, т. Е. Поскольку они могут повторно использоваться в разных контекстах, где нет необходимости в ORM, например. Качающийся пользовательский интерфейс. - проверьте, является ли это прокси перед вызовом
equals
. Минусы: не всегда возможно, т. е. иметь дело с коллекциями и неявными вызовамиequals
, например, Map. - Воздержитесь от использования ленивой загрузки. Минусы: не разумно и неэффективно во всех случаях использования.
ОБНОВИТЬ
Снова просматривая EJ2, я считаю, что следующее будет работать для всех сценариев (тип-тип, тип-прокси, прокси-тип и прокси-прокси), но, как указано в одном из комментариев ниже, он может зацикливаться навсегда, если тип сравнивается с совершенно другой тип, например Person.equals(Employee)
, и оба используют одни и те же критерии равенства EJ2.
if (this.getClass() != anObject.getClass())
{
return anObject.equals(this);
}
InvocationHandler
, а условие(this.getClass() == anObject.getClass())
, конечно же, будет оцениваться как ложное. - person SkyWalker   schedule 24.12.2012A
, затемA a = proxy;
- person Aviram Segal   schedule 24.12.2012InvocationHandler
— это то, что JDK использует для прокси-интерфейсов. Когда Hibernate проксирует ваши классы, я на 99% уверен, что он генерирует подкласс вашего класса сущности. (Это происходит при использовании CGLIB, и я не могу представить, как это могло бы работать иначе с Javassist, учитывая, что код, который упоминает Aviram, должен работать.) - person millimoose   schedule 24.12.2012if (other instanceof ThisClass)
. На самом деле, если вы сделаетеequals()
методfinal
, я считаю, что метод будет формально правильным. (Конечно, это предотвратит изменение семантики равенства подклассами - от этого зависит формальная правильность.) - person millimoose   schedule 24.12.2012