Reputation: 657
I have a problem, I am using Hibernate via Spring data and I have this data model (model is much bigger but this is the part that causes problems).
Lets assume we have Entity A
and Entity B
.
Relationship between two entities are Many-to-Many.
I am trying to fetch A records with B
recordes fetched (to prevent lazy loading).
The model is connected like this
On entity A:
@ManyToMany(mappedBy = "items")
private List<BEntity> bs = new ArrayList<>();
On entity B
@ManyToMany
@JoinTable(
name = "a_b",
joinColumns = { @JoinColumn(name = "b_id", referencedColumnName = "id") },
inverseJoinColumns = { @JoinColumn(name = "a_id", referencedColumnName = "id") }
)
private Collection<AEntity> as = new ArrayList<>();
So its typical M:N relationship. And I am trying to retrieve A data like following
@Query("SELECT a FROM AEntity a " +
" LEFT JOIN FETCH a.bs" +
"WHERE a.id IN (:aIds)")
List<AEntity> findX(@NonNull @Param("aIds") Collection<Long> aIds);
The resulted SQL is something like
select X -- select fields omitted for simplicity
from item itembo0_
left outer join a_b ab on a.id = ab.a_id
left outer join b b on ab.b_id = b.id
where a.id in (...)
Which is a thing I would expect. The SQL will result duplicites (which I would expect as well cause there might be many B records which each has one result row). But at the end, hibernate does not merge all these rows into a A entity with fetched B fields.
For example, when I pass a 5 IDS into "in" condition, I get a 10 A records. Each one has a 2 B records linked! Thats the weird part.
Is there anyone who can tell me why hibernate does not merge these SQL results by A.id identifier and makes duplicites? Is it because I am asking for a List instead of Set?
Upvotes: 3
Views: 3114
Reputation: 98
Using the "DISTINCT" keyword in your query should be enough to avoid duplicates:
@Query("SELECT DISTINCT a FROM AEntity a " +
" LEFT JOIN FETCH a.bs" +
"WHERE a.id IN (:aIds)")
List<AEntity> findX(@NonNull @Param("aIds") Collection<Long> aIds);
I do not know what kind of data you store, but perhaps a better solution, as you have mentioned, would be to use a Set instead of a List.
Upvotes: 4