Во-первых, два правила:
- Доверенные делегат все неконечное вызовы методов целевого экземпляра, за исключением метода для получения идентификатора, если доступ к свойству для идентификатора определяется в отображениях.
- Объекты прокси-объекта: never Инициализирован, экземпляр объекта инициализирован.
1) Предположим, что вы вызываете a.equals(b)
где оба a
и b
являются прокси одного и того же лица. И давайте говорить, что equals
метод реализуется следующим образом:
public boolean equals(Object other) {
...
if (this.someField.equals(other.someField)) {
...
}
...
}
Метод a
equals
делегирован целевой экземпляр форсирования его полная инициализации. Таким образом, вы небезопасны относительно полей в экземпляре a
(вы можете использовать их напрямую).
Однако доступ к полям непосредственно в b
(например other.someField
) является никогда действует. Не имеет значения, инициализирован ли b
или нет, экземпляр прокси никогда не инициализируется, а только целевой экземпляр. Итак, someField
всегда null
в примере b
.
Правильная реализация является использование методов получения, по крайней мере для other
например:
this.someField.equals(other.getSomeField())
или быть последовательным:
this.getSomeField().equals(other.getSomeField())
вещи разные, когда речь идет о final
методов - Hibernate не может переопределить их для делегирования вызова целевой. Итак, если метод equals
был в final
в предыдущем примере, вы получите NullPointerException
при доступе к this.someField
.
Все это можно избежать, настроив Hibernate на использование инструментария байт-кода вместо прокси-серверов, но у этого есть свои собственные подводные камни и он не принят широко.
2) Опять же, он никогда не инициализирует экземпляр прокси. Когда дело доходит до инициализации целевого экземпляра, это зависит от того, определяется ли поле или доступ к свойствам в сопоставлениях. В обоих случаях используется рефлексия (для назначения значений непосредственно полям в случае доступа к полю или для вызова сеттеров в случае доступа к свойствам).