简体   繁体   English

使用JPA / HQL从多对多关系中检索列表

[英]Retrieveing list from a many-to-many relation with JPA/HQL

I have 3 classes, I am trying to get a list of all the events of an eventhost that a user is subscribed to. 我有3个课程,我试图获取用户已预订的eventhost的所有事件的列表。 I am probably thinking way too complicated but I have very little experience with JPA/HQL. 我可能认为方法过于复杂,但是我对JPA / HQL的经验很少。

User class 用户类别

@ManyToMany
    @JoinTable(name = "Subscriptions", joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id") , inverseJoinColumns = @JoinColumn(name = "event_host_id", referencedColumnName = "id") )
    private List<EventHost> subscriptions;

EventHost class EventHost类

@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinColumn(name = "event_host_id", referencedColumnName = "id", updatable = true)
private List<Event> events;

I tried using this query, but it tells me that subscriptions is not mapped, which it is not since it's not a java class. 我尝试使用此查询,但它告诉我订阅未映射,因为它不是Java类,所以没有映射。

String hql = "SELECT o FROM Event WHERE event_host_id IN (SELECT a FROM EventHost WHERE id IN(SELECT b FROM User WHERE = + " + userid + "))";

I know injecting the userid like this is bad practice, I'm just doing it for testing purposes. 我知道像这样注入用户ID是不好的做法,我只是出于测试目的而这样做。

Please ask if you need something more, I would really like to understand how to write a query for this. 请问您是否还需要其他内容,我真的很想了解如何为此编写查询。

This question should really be HQL with two join tables , but I'll let you change it. 这个问题实际上应该是HQL with two join tables ,但我让您对其进行更改。 Since its HQL, or JPA, it's database independent. 由于其HQL或JPA,它是独立于数据库的。

Anyway, any time you see a OneToMany or ManyToMany relationship you have a join table and so you should be thinking joins. 无论如何,任何时候看到OneToManyManyToMany关系时,您都有一个联接join table ,因此您应该考虑联接。 It's always a good idea to look at the sql create table statements to see what's going on. 查看sql create table语句以查看发生了什么总是一个好主意。 In this case your user_subscriptions join table is: 在这种情况下,您的user_subscriptions表为:

create table user_subscriptions (user_id integer not null, subscriptions_id integer not null)

and your event_host_events join table is this: 您的event_host_events连接表是这样的:

create table event_host_events (event_host_id integer not null, events_id integer not null)

Nothing new there. 那里没有新东西。 When you're trying to get something new working that you don't intuitively understand, break it down into things you can do. 当您尝试获得直觉无法理解的新功能时,请将其分解为可以做的事情。 For example, you can execute two queries, getting a Users subscriptions first, and then getting the Events for those subscriptions: 例如,您可以执行两个查询,首先获取Users订阅,然后获取这些订阅的Events

Query query = session.createQuery("select u.subscriptions from User u where name = :name");  
query.setParameter("name", name);
List<EventHost> subscriptions = query.list();
List<Event> events = new ArrayList<Event>();
Query query2 = session.createQuery("select s.events from EventHost s where id = :id");  
for (EventHost s: subscriptions ) {
    query2.setParameter("id", s.getId());
    events.addAll( query2.list());
}

Not elegant, but it works. 不优雅,但是可以。 Then, keeping join in mind, figure out how to make one statement out of the two of them. 然后,保持join记住,搞清楚如何使一个语句出来他们俩的。

Query query = session.createQuery("select s.events from User u join u.subscriptions s where u.name = :name)");  
query.setParameter("name", name);
return query.list();

The join will use an inner join by default, so you're ok there. 默认情况下,该联接将使用inner join ,因此您可以。 The JPA provider will auto-magically join your three Entity tables and two Join Tables for you: JPA提供程序将为您自动魔术地连接您的三个Entity表和两个Join Tables

select 
    event4_.id as id1_2_
from user user0_ 
    inner join user_subscriptions subscripti1_ on user0_.id=subscripti1_.user_id 
    inner join event_host eventhost2_ on subscripti1_.subscriptions_id=eventhost2_.id 
    inner join event_host_events events3_ on eventhost2_.id=events3_.event_host_id 
    inner join event event4_ on events3_.events_id=event4_.id 
where user0_.name=?

Aren't you glad you don't have to write that query? 您不是很高兴不必编写该查询吗?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM