如何将列表与JPA Hibernate中存在的所有值精确匹配?

oiopk7p5  于 2023-08-06  发布在  其他
关注(0)|答案(2)|浏览(125)

我有一个User实体,其skills属性为List类型。我想根据技能列表查询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中不可能比较两个列表,那么我如何使用CriteriaBuilderCriteriaQuery API来实现这一点呢?

knsnq2tg

knsnq2tg1#

你能做到的

@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);


如果你想要一个解决方案,为用户具有完全相同的技能不超过给定的列表,然后看到这个solution

lrl1mhuk

lrl1mhuk2#

您要解决的问题称为Relational Division

SELECT  u.* FROM App_User u
INNER JOIN
(
SELECT skills FROM App_User WHERE skills IN (list values)
GROUP BY skills
HAVING COUNT(DISTINCT skills) = (size of list)
) w ON u.user_name = w.user_name

字符串

相关问题