Подтвердить что ты не робот

Hibernate: индивидуальная ленивая загрузка, необязательно = false

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

Мой код ( ленивая загрузка здесь не работает, когда я вытаскиваю Person - Address также выбирается):

@Entity
public class Person{

  @Id
  @SequenceGenerator(name = "person_sequence", sequenceName = "sq_person")
  @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "person_sequence")
  @Column(name = "id")
  private long personID;

  @OneToOne(mappedBy="person", cascade=CascadeType.ALL, fetch = FetchType.LAZY)
  private Adress address;
  //.. getters, setters
}

@Entity
public class Address {

  @Id
  @Column(name="id", unique=true, nullable=false)
  @GeneratedValue(generator="gen")
  @GenericGenerator(name="gen", strategy="foreign", [email protected](name="property", value="person"))
  private long personID;

  @PrimaryKeyJoinColumn
  @OneToOne
  private FileInfo person;
}

Но: если я добавлю optional=false в отношения OneToOne, ленивая загрузка отлично работает!

@OneToOne(mappedBy="person", cascade=CascadeType.ALL, optional = false, fetch = FetchType.LAZY)
private Adress address;

Вопрос /Entreaty:, пожалуйста, объясните мне, как аннотация optional=false помогает достичь ленивой загрузки.

PS Я читал сообщения post1 и post2, и понять, почему простой OneToOne не может быть ленивым, но я до сих пор не могу понять магию optional=false.

4b9b3361

Ответ 1

Если ассоциация является необязательной, Hibernate не имеет способа узнать, существует ли адрес для данного лица без запроса. Таким образом, он не может заполнить поле адреса прокси, потому что не может быть никаких addres, ссылающихся на человека, и он не может заполнить его нулевым, потому что может быть адрес, ссылающийся на человека.

Когда вы делаете обязательную ассоциацию (т.е. optional=false), она доверяет вам и предполагает, что адрес существует, поскольку ассоциация является обязательной. Поэтому он напрямую заполняет поле адреса прокси, зная, что есть адрес, ссылающийся на человека.

Ответ 2

Простейшим является подделка отношений "один ко многим". Это будет работать, потому что ленивая загрузка коллекции намного проще, чем ленивая загрузка одного свойства с возможностью nullable, но в целом это решение очень неудобно, если вы используете сложные запросы JPQL/HQL.

Другим является использование инструментария байт-кода времени сборки. Для получения дополнительной информации, пожалуйста, ознакомьтесь с документом Hibernate: 19.1.7. Использование ленивой выборки свойств. Помните, что в этом случае вам нужно добавить аннотацию @LazyToOne(LazyToOneOption.NO_PROXY) к отношениям один к одному, чтобы сделать ее ленивой. Настройка fetch для LAZY недостаточна.

Последнее решение заключается в использовании инструментария байт-кода времени исполнения, но оно будет работать только для тех, кто использует Hibernate в качестве JPA-провайдера в полномасштабной среде JEE (в таком случае установка "hibernate.ejb.use_class_enhancer" на true должна делать трюк: Entity Manager Конфигурация) или используйте Hibernate с Spring, настроенным для выполнения во время выполнения (этого может быть трудно достичь на некоторых старых серверах приложений). В этом случае требуется также аннотация @LazyToOne(LazyToOneOption.NO_PROXY).