【发布时间】:2015-04-15 07:59:06
【问题描述】:
我有以下实体,为本示例简化:
@Entity
public class Subscription {
@Column
private String user;
@Column
private String sportsTeam;
@ElementCollection
@CollectionTable(joinColumns= @JoinColumn(name="subscription"))
private Set<String> opponents;
@ElementCollection
@CollectionTable(joinColumns= @JoinColumn(name="subscription"))
private Set<String> matchTypes;
}
这用于订阅服务,您可以在其中获取您的球队比赛的结果。用户总是订阅一支球队(例如曼联),订阅零个或多个对手(其中一个空列表表示您对所有对手感兴趣,一个或多个值意味着您只有在球队正在比赛时才会收到通知对手),以及零个或多个比赛类型(例如“友好”、“国内联赛”或“冠军联赛”。
我有一个保存单个匹配结果的对象,我试图弄清楚如何询问数据库哪些订阅对这些结果感兴趣。
我的尝试如下:
final CriteriaBuilder cb = this.entityManager.getCriteriaBuilder();
final CriteriaQuery<Subscription> cq = cb.createQuery(Subscription.class);
final Root<Subscription> root = cq.from(Subscription.class);
final Expression<String> sportsTeam = root.get("sportsTeam");
final Predicate forSportsTeam = cb.equal(sportsTeam, obj.getSportsTeam());
final Expression<Collection<String>> opponents = root.get("opponents");
final Predicate againstOpponent = cb.isMember(obj.getOpponent(), opponents);
final Expression<Collection<String>> matchTypes = root.get("matchTypes");
final Predicate withMatchType = cb.isMember(obj.getMatchType(), matchTypes);
cq.select(root).where(forSportsTeam, cb.or(againstOpponent, withMatchType));
final TypedQuery<Subscription> qry = this.entityManager.createQuery(cq);
final List<DSubscription> subscriptions = qry.getResultList();
问题在于它会为对手和匹配类型生成内连接:
SELECT t0.ID
,t0.user
,t0.sportsteam
FROM Subscription_MATCHTYPES t2
,Subscription_OPPONENTS t1
,subscription t0
WHERE (t0.sportsteam = 'Manchester United')
AND ((t1.teamName = 'Manchester City') OR (t2.matchType = 'domestic league'))
AND (t1.subscription = t0.ID) AND (t2.subscription = t0.ID)
所以如果对手匹配了订阅,但是没有为订阅选择 matchType,这会给出 0 结果。
如果我要检查的结果对象与此订阅的至少一个对手匹配(或匹配,如果此订阅未指定对手)并且匹配,我正在寻找的是结果查询给出 1 个结果至少有一个 matchType(如果没有为订阅指定 matchType,则始终匹配)。
有什么建议吗?
【问题讨论】:
标签: java jpa eclipselink criteria