使用三个 OR 谓词进行多个联接的 JPA Critiera 查询

发布于 2024-12-11 07:16:07 字数 1544 浏览 0 评论 0原文

我正在使用 JPA Criteria API 编写一个查询,我希望获取与以下任何谓词匹配的所有旅行:

  • 获取我拥有的所有旅行 (MasterTravels)(所有者 = 用户)
  • 获取我作为乘客的所有旅行(乘客、用户 = user)
  • 获取我已应用的所有旅行 (MasterTravelApplication, user = user)

第一个谓词很简单。我只是检查 MasterTravel 中的所有者是否=用户。对于第二个谓词,我需要加入 MasterTravel->MTT->Travel->Passenger,然后检查 Passenger_.user = user。对于第三个谓词,我需要加入另一个方向 MasterTravel->MasterTravelApplication 并检查 MasterTravelApplication_.user = user。这就是破坏我的查询的原因,因为我已经让两个首先工作了,但是当我尝试添加最后一个谓词时,它停止工作。

我应该为最后一个连接创建一个新的根,还是如何获取下面的连接 1 和连接 2 的并集?

CriteriaQuery<MasterTravel> q = cb.createQuery(MasterTravel.class);
Root<MasterTravel> root = q.from(MasterTravel.class);

// Joins 1, these works fine
Join<MasterTravel, MTT> mtts = root.join(MasterTravel_.mtt);
Join<MTT, Travel> travels = mtts.join(MTT_.travel);
Join<Travel, Passenger> passengers = travels.join(Travel_.passengers);                      

// Joins 2, this doesn't work
Join<MasterTravel, MasterTravelApplication> application = root.join(MasterTravel_.applications);

Predicate p = cb.or(
    cb.equal(passengers.get(Passenger_.user), user), 
    cb.equal(root.get(MasterTravel_.owner), user),
    cb.equal(application.get(MasterTravelApplication_.user), user));  // When I add this it stops working

q.select(root);
q.where(p);         
q.orderBy(cb.desc(root.get(MasterTravel_.createdTimestamp)));                       
q.distinct(true);

List<MasterTravel> resultList = em.createQuery(q).getResultList();

I'm writing a query using JPA Criteria API where I want to get all travels matching any of these predicates:

  • Get all travels (MasterTravels) that I own (owner = user)
  • Get all travels where I am a passenger (Passenger, user = user)
  • Get all travels that I have applied to (MasterTravelApplication, user = user)

The first predicate is easy. I just check if owner = user in MasterTravel. For the second predicate I need to join MasterTravel->MTT->Travel->Passenger and then check if Passenger_.user = user. For the third predicate I need to join in another direction MasterTravel->MasterTravelApplication and check for MasterTravelApplication_.user = user. This is what breaks my query since I've got the two first working but when I try to add the last predicate it stops working.

Should I make a new root for the last join, or how can I take the union of Joins 1 and Joins 2 below?

CriteriaQuery<MasterTravel> q = cb.createQuery(MasterTravel.class);
Root<MasterTravel> root = q.from(MasterTravel.class);

// Joins 1, these works fine
Join<MasterTravel, MTT> mtts = root.join(MasterTravel_.mtt);
Join<MTT, Travel> travels = mtts.join(MTT_.travel);
Join<Travel, Passenger> passengers = travels.join(Travel_.passengers);                      

// Joins 2, this doesn't work
Join<MasterTravel, MasterTravelApplication> application = root.join(MasterTravel_.applications);

Predicate p = cb.or(
    cb.equal(passengers.get(Passenger_.user), user), 
    cb.equal(root.get(MasterTravel_.owner), user),
    cb.equal(application.get(MasterTravelApplication_.user), user));  // When I add this it stops working

q.select(root);
q.where(p);         
q.orderBy(cb.desc(root.get(MasterTravel_.createdTimestamp)));                       
q.distinct(true);

List<MasterTravel> resultList = em.createQuery(q).getResultList();

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

书信已泛黄 2024-12-18 07:16:07

您没有描述实体之间的链接,但我猜主旅行不一定至少有一个应用程序,并且由于您正在进行内部联接,因此所有没有任何应用程序的主旅行都是未找到。

使用以 JoinType 作为参数的 join 方法,并使用 JoinType.LEFT

You don't describe the links between entities, but I would guess that a master travel doesn't necessarily have at least one application, and since you're doing an inner join, all the master travels that don't have any application are not found.

Use the join method taking a JoinType as argument, and use a JoinType.LEFT.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文