Ответ 1
Есть две проблемы, препятствующие ленивой загрузке здесь:
- Стратегия выборки по умолчанию
OneToOne
-EAGER
(и имейте в виду, чтоLAZY
- это всего лишь подсказка поставщику персистентности). -
LAZY
может работать только с ассоциациейOneToOne
, если ассоциация не является нулевой (по крайней мере, без использования инструментария байт-кода).
9.1.23 OneToOne Annotation
Аннотация
OneToOne
определяет однозначная связь с другой объект, который имеет один к одному множественность. Это не нормально необходимо указать связанные целевой объект явно, поскольку он может обычно выводятся из типа объект, на который делается ссылка.В таблице 16 перечислены элементы аннотации который может быть указан для
OneToOne
аннотации и значения по умолчанию.@Target({METHOD, FIELD}) @Retention(RUNTIME) public @interface OneToOne { Class targetEntity() default void.class; CascadeType[] cascade() default {}; FetchType fetch() default EAGER; boolean optional() default true; String mappedBy() default ""; }
Я протестировал следующее:
@OneToOne(optional = false, fetch = FetchType.LAZY)
@PrimaryKeyJoinColumn
private UserExt userExt;
И подтвердите, что простой from User
загружает только всех пользователей
Hibernate: select user0_.USER_ID as USER1_0_, user0_.FIRST_NAME as FIRST2_0_, user0_.LAST_NAME as LAST3_0_ from USER user0_
И не выполняет N дополнительных запросов, UserExt
загружается лениво.
Итак, если ваша ассоциация является обязательной, используйте соответствующее сопоставление. И если это необязательно, вам нужно либо:
- использовать инструментарий для байт-кода и выбор без прокси (см. соответствующий вопрос ниже)
- использовать поддельный ManyToOne вместо этого (не тестировал это сопоставление с общим первичным ключом)
- Загрузите UserExt с помощью
join fetch
, чтобы избежать N последующих выборок (конечно, это как-то поражает точку отдельной таблицы)
Обратите внимание, что Hibernate >= 3.x игнорирует аннотацию Fetch при использовании интерфейса Query. В этом случае вам нужно написать это явно. это пример:
EntityManager em = [...]
[...]
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<User> criteria = builder.createQuery(User.class);
Root<User> usersRoot = criteria.from(User.class);
usersRoot.fetch("Address", JoinType.LEFT);
List<User> users = em.createQuery(criteria).getResultList();
Связанные вопросы
- Отношение OneToOne с общим первичным ключом генерирует n + 1 selects; любое обходное решение?
- Создание отношения OneToOne lazy
- fetchmode в jpa 2 criteriaquery
Ссылка
- Спецификация JPA 1.0
- Раздел 9.1.23 "OneToOne Annotation"