Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OneToMany relationship is not working

Tags:

My Tables:

Product: id, name

Offer: id, value, product_id

Entities:

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

When I try to get some data from table Product, I get a java.lang.NullPointerException, and this code: product.getOffers() returns:

{IndirectSet: not instantiated}

How to fix this?

like image 376
Emanuel Avatar asked Nov 28 '11 20:11

Emanuel


People also ask

What is difference between OneToMany and ManyToOne?

Many-to-One relationship in DBMS is a relationship between more than one instances of an entity with one instance of another entity. A project can have more than one student working on it. A team of five students in a college in assigned a project that they need to complete in let us say one month.

What is mappedBy in OneToMany?

The mappedBy attribute of the @OneToMany annotation references the post property in the child PostComment entity, and, this way, Hibernate knows that the bidirectional association is controlled by the @ManyToOne side, which is in charge of managing the Foreign Key column value this table relationship is based on.

What is ManyToOne relationship?

A many-to-one relationship is where one entity (typically a column or set of columns) contains values that refer to another entity (a column or set of columns) that has unique values.

How do you make a one-to-many relationship as bidirectional?

Bidirectional @OneToMany Relationship – Employer/EmployeeWhen you traverse from the “Many” side to the “One” side, you only need to make reference to one object, which is why the Employee class holds a single reference to an Employer class via the private Employer employer instance variable.


2 Answers

This not an error message. The print instruction results in toString() being invoked on the underlying IndirectSet.

TopLink will place an IndirectSet in the instance variable when the containing domain object is read from the datatabase. With the first message sent to the IndirectSet, the contents are fetched from the database and normal Set behavior is resumed.

IndirectCollection types are specifically implemented not to instantiate on toString():

For debugging purposes, #toString() will not trigger a database read.

However, any other call on the indirect collection, e.g., size() or isEmpty() will instantiate the object.

The database read is ultimately triggered when one of the "delegated" methods makes the first call to getDelegate(), which in turn calls buildDelegate(), which sends the message getValue() to the value holder. The value holder performs the database read. With the first message sent to the IndirectSet, the contents are fetched from the database and normal Set behavior is resumed.

See also IndirectList: not instantiated

like image 173
Tomasz Avatar answered Nov 11 '22 04:11

Tomasz


If you get {IndirectSet: not instantiated} when accessing product.getOffers() than most probably you're executing this code outside of the transaction.

By default @OneToMany and @ManyToMany relationships are lazy loaded which means that, for better performance, you'll get data fetched only when you want to access it for the first time. This must happen within an active transaction.
If you don't access this data within this scope than you cannot access this data no more. You should either put your invocation code within the active transaction or change the collection to be eager instead of lazy:

@OneToMany(mappedBy="product", fetch=FetchType.EAGER) 
like image 38
Piotr Nowicki Avatar answered Nov 11 '22 04:11

Piotr Nowicki