Отношения OneToMany не работают - PullRequest
20 голосов
/ 29 ноября 2011

Мои таблицы:

Продукт : идентификатор, имя

Предложение : идентификатор, значение, идентификатор продукта

Объекты:

@Entity
@Table(name="product")
public class Product implements Serializable {
    @OneToMany(mappedBy="product")
    private Set<Offer> offers;
    ...
}

@Entity
@Table(name="offer")
public class Offer implements Serializable {
    @ManyToOne
    @JoinColumn(name="PRODUCT_ID")
    private Product product;
    ...
}

Когда я пытаюсь получить некоторые данные из таблицы Product, я получаю java.lang.NullPointerException, и этот код: product.getOffers() возвращает:

{IndirectSet:не создан}

Как это исправить?

Ответы [ 4 ]

26 голосов
/ 24 августа 2012

Это , а не сообщение об ошибке.В результате выполнения инструкции печати toString () вызывается для базового IndirectSet .

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

Типы IndirectCollection специально реализованы, чтобы не создавать экземпляры для toString () :

В целях отладки #toString () не будет запускать чтение из базы данных.

Однако любой другой вызов косвенной коллекции,например, size () или isEmpty () будут создавать экземпляр объекта.

Чтение базы данных в конечном счете инициируется, когда один из «делегированных» методов делает первый вызов getDelegate (), который, в свою очередь, вызываетbuildDelegate (), который отправляет сообщение getValue () держателю значения.Держатель значения выполняет чтение базы данных.С первым сообщением, отправленным в IndirectSet, содержимое извлекается из базы данных и возобновляется нормальное поведение Set.

См. Также IndirectList: не создан

13 голосов
/ 29 ноября 2011

Если вы получаете {IndirectSet: not instantiated} при доступе к product.getOffers(), то, скорее всего, вы выполняете этот код вне транзакции.

По умолчанию отношения @OneToMany и @ManyToMany загружаются с отложенной загрузкой , что означает, что для повышения производительности вы будете получать данные только тогда, когда захотите получить к ним доступ в первый раз,Это должно происходить в активной транзакции.
Если вы не обращаетесь к этим данным в этой области, вы больше не можете получить доступ к этим данным.Вы должны либо поместить свой код вызова в активную транзакцию, либо изменить коллекцию на eager вместо lazy:

@OneToMany(mappedBy="product", fetch=FetchType.EAGER)
6 голосов
/ 03 апреля 2012

Вот что я сделал

// force load of the set.
entity.getSecrets().isEmpty();
System.out.println(entity.getSecrets());
0 голосов
/ 26 апреля 2018

Это решило мою проблему

@ OneToMany (mappedBy = "columnName", каскад = {CascadeType.ALL}, fetch = FetchType.EAGER)

...