【发布时间】:2018-12-04 11:51:33
【问题描述】:
我有两张桌子 - user 和 booking。每个用户可能有许多预订(一对多的关系)。
user: booking:
id | name | id | country | user_id | price |
-------------| ------------------------------------|
1 | Alice | 1 | Italy | 1 | 2000 |
2 | Bob | 2 | France | 1 | 2500 |
3 | Spain | 1 | 3000 |
我想使用Query DSL 选择所有用户和所有预订价格大于 2000 的预订。如果用户没有任何预订或预订不符合条件我仍然想选择该用户。
首先,让我们看看使用简单的 SQL 左连接查询会是什么样子:
SELECT u.*, b.* FROM user u LEFT JOIN booking b ON u.id = b.user_id AND b.price > 2000
上述查询应提供以下结果:
id | name | id | country | user_id | price |
-------------|----------------------------------------|
1 | Alice | 2 | France | 1 | 2500 |
1 | Alice | 3 | Spain | 1 | 3000 |
2 | Bob | null | null | null | null |
现在我想使用 JPA 和 Query DSL 来实现
JPA 相关的东西:
@Entity
public class User {
@Id
private Long id;
private String name;
@OneToMany(cascade = ALL, fetch = EAGER, orphanRemoval = true, mappedBy = "user")
private List<Booking> bookings;
// getters and setters
}
@Entity
public class Booking {
@Id
private Long id;
private String name;
private Integer price;
@ManyToOne(fetch = LAZY)
@JoinColumn(name = "user_id")
private User user;
// getters and setters
}
查询 DSL:
public List<User> getUsersAndBookings() {
QUser user = QUser.user;
QBooking booking = QBooking.booking;
JPAQuery<User> jpaQuery = new JPAQuery(entityManager);
List<User> result = jpaQuery.from(user).leftJoin(user.bookings, booking).on(booking.price.gt(2000)).fetchJoin().fetch();
return result;
}
事实上,这段代码不起作用,我得到以下异常:
org.hibernate.hql.internal.ast.QuerySyntaxException: with-clause not allowed on fetched associations; use filters [select user from com.example.demo.entity.User user left join fetch user.bookings as booking with booking.price > ?1]
问题是在on方法-on(booking.price.gt(2000))中指定了条件子句。
经过一番研究,我发现这个条件应该在where方法中指定,应该是这样的:
List<User> result = jpaQuery.from(user).leftJoin(user.bookings, booking).where(booking.price.gt(2000)).fetchJoin().fetch();
这可行,但不是我期望的那样,因为它不会返回所有用户,它只返回一个用户(Alice),该用户有一些预订,与条件子句匹配。基本上,它只是过滤合并表(左连接操作后的结果表),这不是我要找的。p>
我想检索所有用户,如果没有特定用户的任何预订,则只需使用 null 而不是该用户的预订列表。
请帮忙,已经挣扎了几个小时没有任何成功。
使用的版本:
- Spring Boot 2.0.2
- Spring Data JPA 2.0.7
- 休眠 5.2.16.Final
- 查询DSL 4.1.4
【问题讨论】:
-
您对此有什么解决方案吗?我有同样的要求 - 需要将用户加载到结果列表中,即使他的所有预订都不符合条件。在那里,我更喜欢带有空预订列表的用户对象。 @leopal 的回答没有这样做。
-
解决了。请看下面我的回答。 stackoverflow.com/a/69421978/5035525
标签: java sql hibernate jpa querydsl