首页 > 解决方案 > JPA - 从列表中查找表中不存在的项目

问题描述

给定一个电子邮件列表,我需要找出表格中不存在哪些电子邮件。使用 SQL,我可以执行以下操作:

SELECT e.email 
FROM 
(
  VALUES('email1'),('email2'),('email3'),('email4')
) AS e(email)
EXCEPT
SELECT username FROM dbo.UsersTbl;

如何编写等效的 JPQL?在应用程序中, values email1, email2... 需要根据传入的列表动态构建(而不是硬编码)。使用 Spring Data JPA 本机查询,我可以执行以下操作:

@Query( value = 
"SELECT e.email " +
" FROM " +
"( " +
"  VALUES('email1'),('email2'),('email3'),('email4') " +
" ) AS e(email) " +
" EXCEPT " +
" SELECT username FROM dbo.UsersTbl ",
nativeQuery=true)
List<String> findMissingEmails(List<String> emails);

但是如何将电子邮件列表传递给查询?

标签: jpaspring-data-jpa

解决方案


对于固定数量的电子邮件参数,这可能有效:

@Query( value = 
"SELECT e.email " +
" FROM " +
"( " +
"  VALUES(:email1),(:email2),(:email3),(:email4) " +
" ) AS e(email) " +
" EXCEPT " +
" SELECT username FROM dbo.UsersTbl ",
nativeQuery=true)
List<String> findMissingEmails(String email1, String email2, String email3, String email4);

对于大量和/或动态的电子邮件,更好的方法可能是使用在运行时构建的NativeQuery


旧答案- 或多或少与所要求的完全相反,但我会将其保留在这里作为参考。

使用命名参数

    @Query("SELECT u.email FROM User AS u WHERE u.email NOT IN (:emails)")
    List<String> findMissingEmails(@Param("emails")Collection<String> emails);

或者,您可以使用JPA 查询方法

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
    List<User> findAllByEmailNotIn(Collection<String> emails);
}

不幸的是,该方法会获取并返回一个Users 列表而不是他们的电子邮件列表。

要仅获取电子邮件,您可以使用JPA 投影

假设User实体有一个String名为的字段,email可以使用以下投影:

public interface UserEmail {
    String getEmail();
}

这是存储库方法:

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
    List<UserEmail> findAllByEmailNotIn(Collection<String> emails);
}

推荐阅读