Почему Hibernate возвращает прокси-объект? - PullRequest
6 голосов
/ 07 апреля 2010

У меня есть сервисный метод, который вызывает DAO, который затем возвращает объект из базы данных. Этот метод вызывается из многочисленных частей системы. Тем не менее, один конкретный метод получает возвращаемый тип ObjectClass _ $$ _ javassist_somenumber в качестве типа. Который отбрасывает вещи. Я вызываю сервисный метод точно так же, как и везде, так почему бы hibernate возвращал прокси, а не естественный объект?

Я знаю, что есть способы выставить «прокси» объект, но я не чувствую, что должен это делать.

Запрос просто

hibernateTemplate.find("from User u where u.username = ?", username)

Я использую Hibernate 3,3 кстати.

Ответы [ 3 ]

8 голосов
/ 07 апреля 2010

Это объект с прокси для поддержки отложенной загрузки; в основном, как только вы ссылаетесь на дочерний или поисковый объект с помощью методов доступа / получателя, если связанный объект не находится в кэше сеанса, то прокси-код отправляется в базу данных и загружает связанный объект. Он использует javassist для эффективной динамической генерации подклассовых реализаций ваших объектов (хотя я думаю, что он также может быть настроен на использование CGLIB ).

Если бы он не был проксирован таким образом, было бы практически невозможно реализовать бесшовную ленивую загрузку.

Я не могу вспомнить с головы до головы, что если вы используете энергичную загрузку, то будет ли вместо этого возвращен естественный объект. Я бы вообще не рекомендовал использовать энергичную загрузку, особенно если у вас много связанных дочерних объектов, так как вскоре это может стать огромным узким местом производительности, так как оно впитает каждый связанный объект в память.

Кроме того, если вам нужно различать тип класса, вместо использования obj.getClass(), используйте Hibernate.getClass(obj), который вернет вам класс естественного объекта независимо от того, прокси он или нет: см. Javadocs API Hibernate здесь .

2 голосов
/ 28 мая 2017

По моему мнению это выражение:

hibernateTemplate.find("from User u where u.username = ?", username)

Должно всегда возвращать POJO, а не прокси.Это связано с тем, что стандартные HQL / критерии возвращают объект без прокси, но объекты ваших исходных классов сущностей.Это отличается от ленивых ассоциаций извлечения:

@Entity
class X {
    @ManyToOne(fetch = FetchType.LAZY)
    private User user;
}

Получение X объекта из БД здесь, у нас будет ленивый прокси в поле X.user (прокси Userэкземпляр).

Теперь, случается, что при выполнении from User where [...] у вас иногда есть POJO, а иногда прокси-объект.Обычно это происходит из-за того, что в некоторых исполнениях User объект был сначала извлечен из БД через ассоциации (запрос from X where [...] был вызван первым в данном сеансе гибернации).Имея уже (прокси) экземпляр User, hibernate будет использовать этот экземпляр повторно даже для ваших простых запросов, таких как from User where [...].

1 голос
/ 07 апреля 2010

Hibernate возвращает прокси, если не все члены разрешены, то есть объект не завершен. Это часто желаемая функция для улучшения производительности и (я думаю) настройка по умолчанию в спящем режиме.

Если вы не хотите использовать прокси, вы можете запретить отложенную загрузку в файле hbm.xml, т.е. использовать готовую загрузку. Пожалуйста, проверьте документацию гибернации для точного синтаксиса.

Чтобы использовать прокси-объект, просто никогда не обращайтесь к члену напрямую, а только через геттер, даже внутри функций-членов. Спящая магия заполняет члена, когда вы его получаете. Таким образом, вам никогда не придется выставлять объект. Также не используйте instanceof на потенциальных прокси-объектах. Но это все равно кодовый запах.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...