Reputation: 131456
I use EclipseLink for 9 months and so far no problem. Since I have the need to query an entity with a OneToMany attribute, it's all the contrary. It gives me a strange result. I have simplified my entities until the maximum but the problem remains.
I will explain my need which is ultra simple : I have two entities : Person which has a bidirectional relation with Address. Person has potentially several Addresses but an Address belongs to one and only Person.
In Classes, it gives that :
@Entity
public class Person implements Serializable {
@Id
private Long id;
@OneToMany(mappedBy = "person", fetch = FetchType.LAZY)
private Set<Address> addresses;
// Getter and setter
...
}
@Entity
public class Address implements Serializable {
@Id
private String idAddress;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "idPerson", referencedColumnName = "idPerson")
private Person person;
// Getter and setter
...
}
I want to query personne with their adresses. All that with some conditions on personne and adresse. My simplified query :
select pers FROM Person pers join pers.addresses address
where pers.matricule=:matricule
and address.date=:dateContract
When I execute it, I retrieve the right person but with all addresses linked (with foreign key) with this person. Even the addresses which don't match with the dateContract condition.
It seems that it's a problem related to the use of filtering on a oneToMany attribute in my query. The problem is solved if i do several requests but it will give low performances as I have several requests like this. I have tried with the oneToMany in eager initialization and with a fetch-join query hint but i have got the same result.
Thank you for having read me :)
PS : I have written the code manually, so a little typo is not impossible
David
Upvotes: 2
Views: 1232
Reputation: 691943
Your query only returns persons. Once you get the persons, you're calling getAddresses(), which lazily loads the addresses of the person - all of them. In short, the query limits the set of returned persons, but since it only returns persons, the addresses are lazy-loaded using another query when accessing the set of addresses.
What you want to do is return the persons with some of their addresses in a single query. To do that, you need to use the fetch
keyword:
select distinct pers FROM Person pers
join fetch pers.addresses address
where pers.matricule = :matricule
and address.date = :dateContract
Be very careful, though: this query returns an incorrect view of the person entity. You should make sure not to modify the collection of addresses of the returned persons (although since the addresses association is mapped by the Address.person
association and there is no cascade, you should not have problems in this particular case).
Upvotes: 1