原始here,遇到了同样的问题,因此尝试在此处交叉发布
我有两个表-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 |
我想使用Hibernate HQL选择所有预订价格大于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();
这有效,但不是我期望的那样,因为它不会返回所有用户,所以它仅返回一个用户(爱丽丝),该用户具有一些与条件子句匹配的预订。基本上,它只是过滤合并的表(左联接操作后的结果表),而这并不是我想要的。
我想检索所有用户,如果特定用户没有任何预订,那么只需null
,而不是该用户的预订列表。