JPA 2.0 / Hibernate: почему LAZY выборка с "@OneToOne" работает из коробки? - PullRequest
7 голосов
/ 22 сентября 2011

мой вопрос касается JPA 2.0 с Hibernate, отношениями @OneToOne и отложенной загрузкой.

Сначала мои настройки:

  • Spring 3.0.5.RELEASE
  • SprnigData JPA 1.0.1. РЕЛИЗ
  • Hibernate 3.5.2-Final
  • СУБД: PostgreSQL 9.0

Недавно я столкнулся с тем фактом, что отношение @OneToOne не может быть получено ленивым способом (FetchType.LAZY), по крайней мере, без инструментария байтового кода, переплетения времени компиляции и т.п. Многие сайты говорят об этом, например:

Дело в том, что с моей настройкой ленивая загрузка сущности @OneToOne работает "из коробки", и я действительно хотел бы понять, почему. Пожалуйста, посмотрите на мой юнит тест:

@Test
@Transactional
public void testAvatarImageLazyFetching()
{
    User user = new User();
    user.setAvatarImage( new AvatarImage() );

    User = userRepository.save( user );

    entityManager.flush();
    entityManager.clear();

    User loadedUser = userRepository.findOne( user.getId() );
    assertNotNull( loadedUser );

    PersistenceUtil persistenceUtil = Persistence.getPersistenceUtil();

    assertTrue( persistenceUtil.isLoaded( loadedUser ) );
    assertFalse( persistenceUtil.isLoaded( loadedUser, "avatarImage" ) );
}

Этот тестовый пример успешен, и в выводе журнала SQL Hibernates я ясно вижу, что «avatarImage» не будет выбираться, только «пользователь» (только один SELECT, нет JOIN, нет доступа к » Таблица "AvatarImage" и т. Д.)

Однонаправленный магазин отношений @OneToOne в классе User выглядит следующим образом:

@OneToOne( cascade = CascadeType.ALL, fetch = FetchType.LAZY )
private AvatarImage    avatarImage;

Итак, все очень просто - и, кажется, работает.

Повторяю мой вопрос: почему он работает, почему "AvatarImage" может быть извлечен лениво, хотя на него ссылается ассоциация @OneToOne?

Я очень ценю любую помощь, которую вы можете предложить

Большое спасибо!

Ответы [ 2 ]

8 голосов
/ 13 сентября 2012

Проблема с отложенной загрузкой отношения OneToOne заключается только в его обратной части (той, которая помечена атрибутом mappedBy). Это прекрасно работает на стороне владения отношениями. T Разница между ними очевидна на уровне базы данных. В вашем случае вопрос заключается в том, содержит ли таблица базы данных пользователей идентификатор AvatarImage в качестве одного из столбцов или наоборот. Если в таблице User есть столбец с идентификатором AvatarImage, то отложенная загрузка будет работать, как вы сказали «из коробки», но не будет работать наоборот.

3 голосов
/ 22 сентября 2011

Ленивое извлечение работает из коробки для @OneToOne аннотированных отношений с провайдером Hibernate JPA, когда выполняется некоторая форма инструментирования байт-кодом. В вашем случае мы могли бы исключить инструментарий во время сборки (исходя из вашего комментария, что он работает «из коробки»). Это оставляет вам возможность ткачества во время выполнения, что вполне возможно в Hibernate & Spring. В последних выпусках Hibernate Javassist используется в качестве среды инструментария байт-кода среды выполнения для Hibernate, в отличие от другой альтернативы CGLIB (, которая устарела после Hibernate 3.5.5 ).

На вопрос, включен ли Javassist в Spring, довольно просто ответить. Для Hibernate EntityManager (который является поставщиком JPA 2.0, который делегирует Hibernate Core) требуется Javassist, и, следовательно, он должен находиться в пути к классам Hibernate, что позволяет выполнять переплетение классов во время выполнения. Вы можете подтвердить это, установив точку останова (в удаленном отладчике, подключенном к вашему серверу приложений), и вы заметите, что управляемый экземпляр Hibernate класса User не будет содержать ссылку на экземпляр AvatarImage; скорее, он будет содержать ссылку на расширенный класс с именем, подобным <package_name>.AvatarImage_$$_javassist_0 (это прокси, который позволяет выполнять отложенную выборку).

...