title: Joining to ElementCollections to find at least one match
body: <p>I have the following entity, simplified for this example:</p>
  
  <pre><code>@Entity
  public class Subscription {
     @Column
     private String user;
  
     @Column
     private String sportsTeam;
  
     @ElementCollection
     @CollectionTable(joinColumns= @JoinColumn(name="subscription"))
     private Set&lt;String&gt; opponents;
  
     @ElementCollection
     @CollectionTable(joinColumns= @JoinColumn(name="subscription"))
     private Set&lt;String&gt; matchTypes;
  }
  </code></pre>
  
  <p>This is used for a subscription service where you can get results of matches your team plays. A user is always subscribed to a team (for instance Manchester United), to zero or more opponents (where an empty list represents that you're interested in all opponents and one or more values means you only get notified if the team is playing that opponent), and to zero or more match types (for instance 'friendly', 'domestic league' or 'champions league'.</p>
  
  <p>I have an object which holds results for a single match and I'm trying to figure out how to ask the database which subscriptions are interested in those results.</p>
  
  <p>My attempt is as follows:</p>
  
  <pre><code>final CriteriaBuilder cb = this.entityManager.getCriteriaBuilder();
  final CriteriaQuery&lt;Subscription&gt; cq = cb.createQuery(Subscription.class);
  final Root&lt;Subscription&gt; root = cq.from(Subscription.class);
  final Expression&lt;String&gt; sportsTeam = root.get("sportsTeam");
  final Predicate forSportsTeam = cb.equal(sportsTeam, obj.getSportsTeam());
  final Expression&lt;Collection&lt;String&gt;&gt; opponents = root.get("opponents");
  final Predicate againstOpponent = cb.isMember(obj.getOpponent(), opponents);
  final Expression&lt;Collection&lt;String&gt;&gt; matchTypes = root.get("matchTypes");
  final Predicate withMatchType = cb.isMember(obj.getMatchType(), matchTypes);
  cq.select(root).where(forSportsTeam, cb.or(againstOpponent, withMatchType));
  final TypedQuery&lt;Subscription&gt; qry = this.entityManager.createQuery(cq);
  final List&lt;DSubscription&gt; subscriptions = qry.getResultList();
  </code></pre>
  
  <p>The problem is that it generates inner joins for the opponents and matchtypes:</p>
  
  <pre><code>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)
  </code></pre>
  
  <p>So if the opponent matches the subscription, but there is no matchType selected for the subscription, this gives 0 result.</p>
  
  <p>What I'm looking for is for the resulting query to give 1 result if the results object I'm checking against matches with at least one opponent for this subscription (or matches if this subscription doesn't specify opponents) and matches with at least one matchType (or always matches if no matchTypes are specified for the subscription).</p>
  
  <p>Any tips?</p>