使用三个 OR 谓词进行多个联接的 JPA Critiera 查询
我正在使用 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您没有描述实体之间的链接,但我猜主旅行不一定至少有一个应用程序,并且由于您正在进行内部联接,因此所有没有任何应用程序的主旅行都是未找到。
使用以
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 aJoinType.LEFT
.