java - JPA (Hibernate)/QueryDSL left join with condition 不起作用

标签 java sql hibernate jpa querydsl

我有两个表 - userbooking .每个用户可能有很多预订(一对多关系)。

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),该用户有一些预订,符合条件子句。基本上,它只是过滤合并表(左连接操作后的结果表),这不是我要找的。

我想检索所有用户,如果没有特定用户的任何预订,那么只需要 null而不是该用户的预订列表。

请帮助,苦苦挣扎了几个小时都没有成功。


使用的版本:

  • Spring 启动 2.0.2
  • Spring 数据 JPA 2.0.7
  • hibernate 5.2.16.Final
  • 查询DSL 4.1.4

最佳答案

您可以在 where 子句中使用 isNull 表达式来获取具有空值的行。

你的查询应该是这样的:

jpaQuery.from(user)
    .leftJoin(user.bookings, booking)
    .fetchJoin()
    .where(booking.price.gt(2000).or(booking.id.isNull())).fetch();

Hibernate 生成的查询:

select
user0_.id as id1_1_0_,
bookings1_.id as id1_0_1_,
user0_.name as name2_1_0_,
bookings1_.country as country2_0_1_,
bookings1_.price as price3_0_1_,
bookings1_.user_id as user_id4_0_1_,
bookings1_.user_id as user_id4_0_0__,
bookings1_.id as id1_0_0__
from
user user0_
left outer join
booking bookings1_
on user0_.id=bookings1_.user_id
where
bookings1_.id is null
or bookings1_.price>?

关于java - JPA (Hibernate)/QueryDSL left join with condition 不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51031350/

相关文章:

java - 如何从eclipse中调用jar包中的主类?

java - 当Redis缓存不可用时如何防止所有RedisConnectionFailureException

mysql - OpenShift 应用程序无法连接到 MySQL : JDBCConnectionException: Could not open connection

java - FetchType.LAZY 不适用于 hibernate 中的 @ManyToOne 映射

java - Hibernate where 子查询

java - socketChannel.register() 和 key.interestOps() 的区别?

java - Eclipse 中的 Angular Js

sql - 使用SQLite的 Entity Framework

java - 如何使用 ORACLE SQLLDR 执行自定义 SQL 命令

mysql - SQL:当 PK 等于同一字段上两个不同行中的两个特定值时返回值