This may seem basic but it's late and I'm having trouble with the following.
class Group {
@Id
String id;
}
class Participation {
@Id
String id;
@ManyToOne
@JoinColumn(name = "GROUP_ID")
Group group;
@ManyToOne
@JoinColumn(name = "USER_ID")
User user;
}
class User {
@Id
String id;
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
Set<Participation> participations;
}
So
Participation -->1 Group
and User 1<-->N Participation
How can I retrieve all Groups with, for a given User, the associated Participation (or null is there is none)? I've been playing with join fetches but to no avail so far...
Many thanks,
CN
PS. I can do this in SQL thus :
select g.d, p.id
from group as g
left join participation as p
on p.group_id = g.id and p.user_id = 2;
(Probably some typo in the HQL itself but the idea should be correct)
What you are asking, based on your SQL and description, is find out all Participation
(and its corresponding Group
) based on User
, which is simply
select p.id, p.group.id from Participation p where p.user.id = :userId
To make it better, you should fetch the entities instead:
from Participation p left join fetch p.group where p.user.id = :userId
There were some confusions in understanding what you were trying to do: You want all groups (regardless of condition). And, for a given user, you want to find all groups and participations that user is involved.
Though it should be possible using Right-outer-join:
select g, p from Participation p
right outer join p.group g
where p.user.id=:userId
Or, in later version of Hibernate (>= 5.1 ?), it allow explicit join (haven't tried before, you may give it a try) (Replace with
with on
if you are using JPQL):
select g, p from Group g
left outer join Participation p
with p.group = g
left outer join p.user u
where u.id = :userId
Or you may use other techniques such as subquery etc. However I would rather separate them into simpler queries in your case and do a simple aggregation in your code.
The basic idea is to have
from Groups
from Participation p join fetch p.group where p.user.id=:userId
Then you can aggregate them easily to the form you want, eg Map<Group, List<Participation>>
, or even more meaningful value object.
The benefit is the data access query is simpler and more reusable (esp if you are wrapping them in DAO/Repository finder method). One more round trip to DB shouldn't cause any obvious performance impact here.
You need to map the participation
relationship in the Group
entity. If the relationship between Participation
and Group
is 1..N:
class Group {
String id
List<Participation> participations
}
The JPQL can be:
SELECT g.id, p.id FROM Group g
JOIN g.participations p
JOIN p.user user
WHERE user.id = :idUser
You can receive this information as List<Object[]>
( Object[0]
is group id and Object[1]
is participation id) or use SELECT NEW .
Without map the Group/Participation relationship, you can do:
SELECT g.id, p.id FROM Group g, Participation p
JOIN p.user user
JOIN p.group groupp
WHERE g.id = groupp.id
AND user.id = :idUser
But you can't do a LEFT JOIN
using this strategy. The query above behaviours like a JOIN
.
It's normal with Hibernate you map the side of a relationship that you would like to make a query. So, I recommend the first approach, mapping the relationship.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.