Spring JPA存储库和QueryDsl如何强制左连接

比方说,我有两个实体User和Task,每个用户可以有一个任务。

我面临的问题是,如果用户表中有一条记录,其电子邮件以a开头,而任务表中根本没有记录。

下面的代码段将不返回任何记录,尽管我希望用户的邮件以a开头。

示例中的UserRepository扩展了QuerydslPredicateExecutor。

        userRepository.findAll(
            QUser.user.email.startsWith("a")
                .or(QUser.user.task.text.contains("something"))
        )

如果我检查日志,则Hibernate将使用user.task_id=task.id创建交叉联接,作为where子句的一部分。如果用户未分配任务,则这种类型的联接会自动丢弃其邮件以a开头的用户。

在存储库的findAll方法中是否有一种方法可以强制使用左联接而不是交叉联接?

我知道我可以使用JPAQuery来做到这一点,但随后我将不得不重新实现分页功能...

        JPAQuery query = new JPAQuery(entityManager);
        query
            .from(QUser.user)
            .leftJoin(QTask.task)
        // ...
lingcy 回答:Spring JPA存储库和QueryDsl如何强制左连接

我不确定是否可以这样做,因为findAll实现是为我们生成的。但是,我们可以在findAll方法中传递谓词,这将有助于处理您遇到的问题。

您可以尝试执行以下操作:

QUser qUser = QUser.user;
QTask qTask = QTask.task;

JPQL<UserEntity> userJpqlQuery = JPAExpressions.selectFrom(qUser)
                                         .leftjoin(qUser.task,qTask)
                                         .where(qUser.email....,qTask.text...);


userRepository.findAll(qUser.in(userJpqlQuery));

在上面的代码中,我使用了 Querydsl ,它是 CriteriaBuilder 的替代方法,并且类型安全。然后,我创建了一个子查询以进行所需的选择,并返回与该子查询匹配的所有用户。

最后,休眠应该生成如下内容:

select * from User qUser0 where qUser0.id.in( 
              select qUser1.id from User qUser1 
              left join Task qTask0 on 
              qUser1.taskId = qTask0.id 
              where ...
              );
本文链接:https://www.f2er.com/3012167.html

大家都在问