Criteria eclipselink join

2019-09-08 18:31发布

问题:

I can't understand how do a join in eclipse link with criteria. This my entity:

public class A implements Serializable {

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Basic(optional = false)
  @Column(name = "id")
  private Long id;
  @Column(name = "value")
  private String value;   

  @OneToMany(mappedBy = "aid")
  private Collection<B> bCollection; 
}

public class B implements Serializable {

  @Id      
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Basic(optional = false)
  @Column(name = "id")
  private Long id;

  @JoinColumn(name = "a_id", referencedColumnName = "id")
  @ManyToOne
  private A aid;  
}

I do this:

    CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery cq = cb.createQuery();
    Root<A> a = cq.from(A.class);
    Join<A, B> j = a.join("aid",JoinType.INNER);
    cq.distinct(true);
    //and now what?        
    cq.where(cb.equal(a.get("id"), "aid"));
    Object r = em.createQuery(cq).getResultList();

And now, how I can to bind my join clause to CriteriaQuery?

回答1:

First, in order to get a result list containing all fields from A and B, you need to shape your results as a list of Tuples or a list of Objects like explained in this article (chapter Projecting the result).

This requires using a multiselect statement or using construct like this:

cq.multiselect(a, b));
cq.select(cb.construct(a, b));

where b should be obtained like this:

CollectionJoin<A, B> b = a.join(A_.bCollection, JoinType.INNER);  // using Metamodel


回答2:

If all you want is "Select a from A a join a.bCollection" such that only As with a B are returned, then all you need is:

CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery cq = cb.createQuery();
Root<A> a = cq.from(A.class);
Join<A, B> j = a.join("bcollection",JoinType.INNER);
cq.distinct(true);
Object r = em.createQuery(cq).getResultList();

JPA will create the A->B table join for you using the relationship defined on B's aid attribute, so you don't need to. Returned A's will be complete, except that since you are using the default fetch type on bCollection mapping, Bs maybe lazily fetched. IF you want them eagerly brought in and associated to the As in a single query, use the fetch method instead of the join:

a.fetch("bcollection",JoinType.INNER);