Hibernate Query 将映射实体集合与给定集合中的至少一个元素匹配,并且不能在另一个多对多关系中匹配
Posted
技术标签:
【中文标题】Hibernate Query 将映射实体集合与给定集合中的至少一个元素匹配,并且不能在另一个多对多关系中匹配【英文标题】:Hibernate Query to match mapped entity collection with at least one element in given collection,and must not match in another, ManyToMany relationship 【发布时间】: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.subscriptions
和subscriptionList
的交集应该至少是一个。
我参考了这篇文章并写了一个查询: 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.subscriptions
和subscriptionList
中至少有一个共同点的读者。
我想要达到的目标:
现在,我有一个restrictedSubscriptionList
,它是SubscriptionEntity
的集合(可以是SubscriptionEntity.name
)。现在我想扩展上面的查询,这样,如果读者订阅了restrictedSubscriptionList
中的任何一个,那么它就不会被获取。这意味着,如果ReaderEntity.subscriptions
和restrictedSubscriptionList
之间的交集不为空,则不应获取 Reader。
到目前为止我尝试了什么:
我尝试将AND NOT IN (:restrictedSubscriptionList)
添加到该查询中,但它似乎有错误的逻辑,并且仍然会填充所有订阅了至少一个restrictedSubscriptionList 的读者。
我手动获取属于restrictedSubscriptionList
的读者并将它们添加到排除为:
WHERE r.username NOT IN (:restrictedSubscriptionList)
但是当这样的读者越来越多时,查询会变大,导致效率降低。
如果有人可以帮助我制定查询,将不胜感激。
非常感谢您抽出宝贵时间阅读我的问题。
【问题讨论】:
【参考方案1】:由于各种原因,您不能也不应该过滤实体的集合。您能做的最好的事情就是只选择那些符合您要求的ReaderEntity
对象。您可以使用以下查询,这在结果集基数方面更好:
from ReaderEntity r
where exists (
select 1
from r.subscriptions s
where s.subscriptionName in :subscriptionList
and s.subscriptionName not in :restrictedSubscriptionList
)
【讨论】:
以上是关于Hibernate Query 将映射实体集合与给定集合中的至少一个元素匹配,并且不能在另一个多对多关系中匹配的主要内容,如果未能解决你的问题,请参考以下文章