views:

64

answers:

1

Hi,

I'm new to JPA and now stuck with a problem!

I have two tables Person and PersonAddress.

In the Person entity, I have

@OneToMany(mappedBy="personid")
private Set<Personaddress> personaddressCollection;

and

public Set<Personaddress> getPersonaddressCollection() {
    return this.personaddressCollection;
}

public void setPersonaddressCollection(Set<Personaddress> personaddressCollection) {
    this.personaddressCollection = personaddressCollection;
}

In the PersonAddress entity, I have

@ManyToOne
@JoinColumn(name="PERSONID")
private Person personid;

I'm doing a query similar to one below:

List<Person> personlist = em.createQuery("SELECT e FROM Person e").getResultList();

I am expecting it to return all the data from Person table along with the data in PersonAddress table in the Set available in Person entity. The size of personlist is correct, but when I try to read the PersonAddress collection, I'm getting null values. But the database has values in it and it cannot be null.

Corresponding to every Partner, there will be a PartnerAddress which will not be null. How do I query it with JPA if whatever I have done so far is wrong?

Please help.

A: 

I am expecting it to return all the data from Person table along with the data in PersonAddress table in the Set available in Person entity.

A OneToMany is LAZY by default so a SELECT e FROM Person e won't load the collection of associated addresses.

If you want to change this behavior, either make the association eager:

@OneToMany(mappedBy="personid", fetch=FetchType.EAGER)
private Set<Personaddress> personaddressCollection;

Or prefetch the association using a FETCH JOIN:

SELECT e FROM Person e LEFT JOIN FETCH e.personaddressCollection

With the later approach, you can still benefit from lazy loading when you don't need the addresses. The former approach changes the behavior "globally".

The size of personlist is correct, but when I try to read the PersonAddress collection, I'm getting null values. But the database has values in it and it cannot be null.

This is somehow "another" issue. My recommendation would be to activate logging of SQL statements to see what query is performed exactly and why you don't get the corresponding addresses. There must be something wrong with the data.

References

  • JPA 1.0 Specification
    • Section 9.1.24 "OneToMany Annotation"
    • Section 4.4.5.3 "Fetch Joins"
Pascal Thivent
"A OneToMany is LAZY by default so a SELECT e FROM Person e won't load the collection of associated addresses.": The first part is correct, but not the second. The collection is loaded, only that the loading is deferred until the getter method is invoked. This is handled by the proxy object on the collection's getter. So, there cannot be a bug in the fetch strategy resulting in null values being returned. The recommendation of logging SQLs is bound to help the OP. I had asked for the complete class listing since I believe that class-entity relationship is not recognized correctly.
Vineet Reynolds
@Vineet That's not what I said. I interpreted the first part of the question *"I am expecting it to return all the data from Person table __along__ with the data in PersonAddress table in the Set available in Person entity"* as being about EAGER fetching which is why I wrote a few words about OneToMany being LAZY by default. But I did NOT write that this could cause getting `null` and actually explicitly wrote that this was *"another"* issue. In other words, maybe the first part goes beyond what the OP is asking but I still consider my answer as correct, you're reading something I didn't say.
Pascal Thivent
@Pascal, my bad. I can only offer a sheepish apology :-)
Vineet Reynolds
@Vineet No problem, don't worry. Maybe my answer is not clear after all. I'll just wait for some feedback from the OP before to update.
Pascal Thivent
I chose to go for SELECT e FROM Person e LEFT JOIN FETCH e.personaddressCollection . Its working fine now. Maybe because I was trying out things, and executed the query right after an insertion. I separated them and tried again, works fine..! Thanks for all the help!
whoopy_whale
@whoopy_whale `Maybe because I was trying out things, and executed the query right after an insertion. I separated them and tried again, works fine..!` Shouldn't be it. Performing a query should `flush` pending changes that could affect the result so you'll get coherent results (that's part of the spec, Section 3.6.2 "Queries and FlushMode").
Pascal Thivent