Hibernate OnetoMany,ManyToOne Mapping Giving null

I have 2 classes called PurchaseList.java and PurchaseListItems.java

I have to map PurchaseList in PurchaseListItems

PurchaseList.java

@OneToMany(cascade = CascadeType.ALL)
@JoinColumn(name="pl_id",referencedColumnName="id")
private List<PurchaseListItems> purchaseListItems;

PurchaseListItems.java

@ManyToOne
@JoinColumn(name="pl_id")
private PurchaseList purchaseListId;

Everything is fine but i am getting null in pl_id. Please tell where i am wrong

Upvotes: 15

Views: 32878

Answers (7)

Chandru
Chandru

Reputation: 1014

For some reason mapped by didn't work for me with postgres sql and Hibernate4

Below mapping worked

PurchaseList.java

@OneToMany(cascade = CascadeType.ALL)
@JoinColumn(name="pl_id",nullable=false)
private List<PurchaseListItems> purchaseListItems;

PurchaseListItems.java

@ManyToOne
@JoinColumn(name="pl_id", nullable=false,insertable=false,updatable=false )
private PurchaseList purchaseListId;

Note: you have to use the Identity or Explicitly mention the Sequence for id columns for postgres.

@GeneratedValue(strategy=GenerationType.IDENTITY)

Upvotes: 8

bennidi
bennidi

Reputation: 2122

Your mapping actually defines two independent unidirectional relations. What you want is one bidirectional relation.The following code will establish the bidirectional relation

@OneToMany(cascade = CascadeType.ALL, mappedBy = "purchaseListId")
@JoinColumn(name="pl_id",referencedColumnName="id")
private List<PurchaseListItems> purchaseListItems;

The mappedBy attribute is necessary since there is no way for the provider to automatically determine that the specified relations actually form a single relation. One could use the Java type of the instance member but then what if you have multiple members of the same type. And there are many scenarios where you have two single relations. Example:

OneToMany: User -> ForumThread (the threads created by the user)

ManyToOne: ForumThread -> User (the user who closed the thread. obviously not necessarily the one who started the thread)

These are two independent relations and must be treated as such. You would be quite surprised if your persistence provide just made a bidirectional relation out of that just because the types and multiplicity matched.

Also note that bidirectional relations are not automatically managed by any JPA provider, meaning that the inverse side is not automatically updated/set in your object model and thus not in the db. You have to do that yourself. By the way, in all my projects bidirectional relationships were a pain in the ass and I think it is advisable to avoid them.

Upvotes: 6

Glen Best
Glen Best

Reputation: 23115

  1. The @JoinColumn annotation belongs on the @ManyToOne side of the relationship - but not on the @OneToMany side - remove it from the @OneToMany side.

  2. Cascade is used to cascade DELETE/READ/UPDATE operations..., but it does not automatically populate the ID column on the "child" side of a foreign key. In fact, it doesn't populate the java references to objects on either side of the FK relationship. You need to manually setup relationship data on both sides of bidirectional relationships:

    myPurchaseListItem.setPurchaseList(myPurchaseList);
    myPurchaseList.setPurchaseListItem(myPurchaseListItem);

    From the JPA 2 spec:

    Bidirectional relationships between managed entities will be persisted based on references held by the owning side of the relationship. It is the developer’s responsibility to keep the in-memory references held on the owning side and those held on the inverse side consistent with each other when they change. In the case of unidirectional one-to-one and one-to-many relationships, it is the developer’s responsibility to insure (sic) that the semantics of the relationships are adhered to.[29]

    It is particularly important to ensure that changes to the inverse side of a relationship result in appropriate updates on the owning side, so as to ensure the changes are not lost when they are synchronized to the database.

Upvotes: 2

for(PurchaseListItems item:purchaseListItemsList)
item.purchaseListId(PurchaseList);

This is what I missed when i am creating an object.

Thnaks for your answers

Upvotes: 1

Henry Leu
Henry Leu

Reputation: 2274

Check if you have populated purchaseListId with valid value (a created PurchaseList instance) when you create a PurchaseListItems value.

It's better to use mappedBy as below code to let many-side to maintian the relationship.

@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "purchaseListId")
@JoinColumn(name="pl_id",referencedColumnName="id")
private List<PurchaseListItems> purchaseListItems;

Upvotes: 0

PSR
PSR

Reputation: 40358

try this

@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "purchaseListId")

Upvotes: 0

MGPJ
MGPJ

Reputation: 1072

The jpa specification looks good, but verify you have given valid parent to child relationship in the database. If there is not a reference then it will return null.

Upvotes: 0

Related Questions