2013-08-01 2 views
42

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

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

@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; 

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

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

+0

Эй, @ Володимир, у меня с вами такая же проблема. Я пытаюсь отделить столбец BLOB от объекта. Родительский объект имеет дочернюю структуру. Детский объект содержит двоичный столбец. Родитель и ребенок являются «той же таблицей», поэтому я использую отношения @OneToOne. Хотя я использовал LAZY fetchType, но, похоже, не работает. Когда я помещаю 'optional = false', он работает. Любое объяснение будет оценено действительно. – Emerald214

+0

@ Emerald214 извините, это было 2 года назад.В настоящее время я пишу JS Mobile и не могу помочь вам –

+0

OneToOne optional = false не работает с CascadeType.PERSIST см: https://hibernate.atlassian.net/browse/HHH-9670 – sliver

ответ

62

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

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

+0

optional = false не работает, если вы пытаетесь сохранить Personne без Adresse: "org.hibernate.PropertyValueException: свойство null-null ссылается на значение null или переходное:" –

+3

optional = false означает, что ... адрес не является необязательным. Так что это обязательно. Поэтому установка этого параметра в значение null вызывает исключение. Это вполне ожидаемо. –

+0

Итак, OneToOne, ленивая загрузка, с общим ключом Primary и опциональным с одной стороны, просто невозможно с спящим режимом, не так ли? –

5

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

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

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

Смежные вопросы