首页 > 解决方案 > 如何将列表与 JPA Hibernate 中存在的所有值完全匹配?

问题描述

我有一个具有属性作为类型列表的User实体。skills我想User根据技能列表查询表格,如果所有技能都存在于技能列中,那么除非没有,否则只会找到匹配项。

我为此使用了 JPQL,但它使用该IN子句一一匹配列表中的每个元素。

用户类

@Entity(name = "App_User")
//table name "user" is not allowed in postgres
public class User {
    @Id
    @GeneratedValue(generator = "UUID")
    @GenericGenerator(name = "UUID", strategy = "org.hibernate.id.UUIDGenerator")
    @Column(name = "user_id", updatable = false, nullable = false)
    @Setter(AccessLevel.NONE)
    private UUID id;

    @Column(name = "user_name")
    @NotBlank(message = "Name is mandatory")
    private String name;

    @Column(name = "user_email")
    @NotBlank(message = "Email is mandatory")
    private String email;

    //    Current point balance of the user
    @Column(name = "points")
    private int points;

    @ElementCollection(fetch = FetchType.EAGER)
    @Column(name = "skills")
    @NotEmpty
    private List<String> skills = new ArrayList();

}

我使用的 JPA 查询是

SELECT u FROM App_User u JOIN u.skills skill where skill in :skillList

如果我想匹配这样的技能列表,Arrays.asList("skill1","skill2","skill3")那么我只想要结果中拥有所有这些技能的用户,而不是一两个。上面使用IN的子句返回相同的结果。

我已经读到无法比较 JPQL 中的两个列表,那么如何使用CriteriaBuilder CriteriaQueryAPI 来实现呢?

标签: javaspringhibernatejpaspring-data-jpa

解决方案


你可以这样做

@Query(value = "SELECT u FROM User u LEFT JOIN u.skills sk WHERE sk IN :skillList"
           + " GROUP BY u HAVING COUNT( sk) = :skillListSize")
List<User> findBySkills(@Param("skillList") List<String> skills,
                                 @Param("skillListSize") long skillListSize);

在这里,按用户分组,然后检查具有所有技能的组或不使用大小。所以它会获取所有拥有所有技能的用户。

或者使用这种方式

@Query(value = "SELECT u FROM User u LEFT JOIN u.skills sk GROUP BY u"
           + " HAVING SUM(CASE WHEN sk IN (:skillList) THEN 1 ELSE 0 END) = :skillListSize")
List<User> findBySkills(@Param("skillList") List<String> skills,
                                 @Param("skillListSize") long skillListSize);

如果您想为具有完全相同技能的用户提供不超过给定列表的解决方案,请参阅此解决方案


推荐阅读