Проживающие в прокси Hibernate прокси и `Object#equals`
При предоставлении #equals
Для реализации UDT в Java одним из условий является то, что переданный аргумент должен быть экземпляром текущего класса, в противном случае мы перестанем работать return false
см. Эффективная Java (EJ2). Однако, при использовании Hibernate 4 мы можем получить экземпляры прокси-сервера javassist из-за отложенной загрузки, где это #equals
условие не выполнится. Что будет лучшим выбором для преодоления этого? Несколько вариантов, которые я могу придумать:
- продлить
equals
Реализация принять во внимание случай прокси. Минусы: стоимость сопровождения, аппаратная зависимость от прокси-инфраструктуры Hibernate, хакерские модели, модели сущностей или доменов должны быть независимыми от используемого ORM, т. Е. Поскольку они могут быть повторно использованы в различных контекстах, где нет необходимости в ORM, например, в Swing UI. - проверьте, является ли это прокси, прежде чем вызывать
equals
, Минусы: не всегда возможно, т.е. иметь дело с коллекциями и неявными вызовамиequals
Например, карта. - Воздержитесь от использования отложенной загрузки. Минусы: не разумно и не эффективно во всех случаях использования.
ОБНОВИТЬ
Повторно рассматривая EJ2, я считаю, что следующее будет работать для всех сценариев (Type-Type, Type-Proxy, Proxy-Type и Proxy-Proxy), но, как указано в одном из комментариев ниже, оно может зацикливаться вечно, если сравнивать Type с совершенно другой тип, например Person.equals(Employee)
и оба используют одинаковые критерии равных EJ2.
if (this.getClass() != anObject.getClass())
{
return anObject.equals(this);
}
4 ответа
Я наткнулся на ту же проблему. То, как я исправил это изменить .equals
-метод.
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!getClass().isAssignableFrom(obj.getClass()))
return false;
AbstractEntity other = (AbstractEntity) obj;
if (getId() == null) {
if (other.getId() != null)
return false;
} else if (!getId().equals(other.getId()))
return false;
return true;
Хитрость заключается в том, чтобы не сравнивать классы, чтобы они были одинаковыми, а использовать isAssignableFrom
-метод. Другой трюк заключается в том, чтобы не использовать прямые свойства (other.id
), но используйте метод ge t (other.getId()
)
У меня нет репутации, чтобы комментировать ответ Виллема де Вит. Чем мне нужно опубликовать новый ответ.
Чтобы решить проблему djechelon, вы должны заменить эту строку:
if (!getClass().isAssignableFrom(obj.getClass()))
за
if ( !obj.getClass().isAssignableFrom(getClass()) && !getClass().isAssignableFrom(obj.getClass()) )
Затем вы убедитесь, что функции equals будут работать для всех сценариев (Type-Type, Type-Proxy, Proxy-Type и Proxy-Proxy).
У меня нет репутации, чтобы голосовать за твой ответ тоже. Я так несчастен!
Ответ DHansen выше близок, но для меня (с помощью Hibernate) это решило проблему:
if (!Hibernate.getClass(this).equals(Hibernate.getClass(obj))) {
return false;
}
по предложению доктора Ханса-Петера Штерра
Также важно всегда использовать "добытчики", как предложено Виллемом де Витом выше.
Вы можете сделать две вещи: 1. Измените equals, чтобы использовать instanceof вместо равенства классов. Тип прокси-сервера не равен типу объекта, а расширяет тип объекта.
- Разверните прокси, чтобы получить саму сущность (есть несколько инструментов гибернации, которые помогут вам сделать это)