【问题标题】:Hibernate Query to match mapped entity collection with at least one element in given collection,and must not match in another, ManyToMany relationshipHibernate Query 将映射实体集合与给定集合中的至少一个元素匹配,并且不能在另一个多对多关系中匹配
【发布时间】:2021-09-18 14:33:55
【问题描述】:

我的所有者实体:

@Entity(name = "SubscriptionEntity")
@Table(name = "SUBSCRIPTION", uniqueConstraints = {
        @UniqueConstraint(columnNames = "ID")})
 
public class SubscriptionEntity implements Serializable 
{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "ID", unique = true, nullable = false)
    private Integer subscriptionId;
 
    @Column(name = "SUBS_NAME", unique = true, nullable = false, length = 100)
    private String subscriptionName;
     
    @ManyToMany(cascade=CascadeType.ALL)
    @JoinTable(name="READER_SUBSCRIPTIONS", joinColumns={@JoinColumn(referencedColumnName="ID")}
                                        , inverseJoinColumns={@JoinColumn(referencedColumnName="ID")})
    private Set<ReaderEntity> readers;
 
    //Getters and setters
}

映射实体:

@Entity(name = "ReaderEntity")
@Table(name = "READER", uniqueConstraints = {
        @UniqueConstraint(columnNames = "ID"),
        @UniqueConstraint(columnNames = "EMAIL"),
        @UniqueConstraint(columnNames = "USERNAME"})
 
public class ReaderEntity implements Serializable 
{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "ID", unique = true, nullable = false)
    private Integer readerId;
 
    @Column(name = "EMAIL", unique = true, nullable = false, length = 100)
    private String email;
 
    @Column(name = "USERNAME", unique = false, nullable = false, length = 100)
    private String username;
 
    @ManyToMany(mappedBy="readers") 
    private Set<SubscriptionEntity> subscriptions;
 
    //Getters and setters
}

现在,我有一个 subscriptionList,其中包含很少的订阅。我想要一个ReaderEntity 对象的分页列表,这些对象的订阅至少属于subscriptionList 中的一个。即ReaderEntity.subscriptionssubscriptionList 的交集应该至少是一个。

我参考了这篇文章并写了一个查询: Hibernate or SQL Query M-N member of with collections?

@Query("SELECT DISTINCT r FROM ReaderEntity r LEFT JOIN r.subscriptions s WHERE (s.subscriptionName in (:subscriptionList))")
Page<User> findAllBySubscriptions(@Param("subscriptionList") Set<String> subscriptionList, Pageable pageable);

这实现了我的目标,即获取在ReaderEntity.subscriptionssubscriptionList 中至少有一个共同点的读者。

我想要达到的目标:

现在,我有一个restrictedSubscriptionList,它是SubscriptionEntity 的集合(可以是SubscriptionEntity.name)。现在我想扩展上面的查询,这样,如果读者订阅了restrictedSubscriptionList 中的任何一个,那么它就不会被获取。这意味着,如果ReaderEntity.subscriptionsrestrictedSubscriptionList 之间的交集不为空,则不应获取 Reader。

到目前为止我尝试了什么: 我尝试将AND NOT IN (:restrictedSubscriptionList) 添加到该查询中,但它似乎有错误的逻辑,并且仍然会填充所有订阅了至少一个restrictedSubscriptionList 的读者。

我手动获取属于restrictedSubscriptionList 的读者并将它们添加到排除为:

WHERE r.username NOT IN (:restrictedSubscriptionList)

但是当这样的读者越来越多时,查询会变大,导致效率降低。

如果有人可以帮助我制定查询,将不胜感激。

非常感谢您抽出宝贵时间阅读我的问题。

【问题讨论】:

    标签: java sql database hibernate jpa


    【解决方案1】:

    由于各种原因,您不能也不应该过滤实体的集合。您能做的最好的事情就是只选择那些符合您要求的ReaderEntity 对象。您可以使用以下查询,这在结果集基数方面更好:

    from ReaderEntity r 
    where exists (
      select 1 
      from r.subscriptions s 
      where s.subscriptionName in :subscriptionList 
      and s.subscriptionName not in :restrictedSubscriptionList
    )
    

    【讨论】:

      猜你喜欢
      • 2021-08-25
      • 2012-11-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多