0

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?

perissf
  • 15,979
  • 14
  • 80
  • 117
Terence
  • 69
  • 1
  • 11
  • 'p' isn't defined, and it is not clear what you are trying to query or why you need the join. Are you trying to fetch b as well as A? ie "select a from A a join fetch a.bCollection where a.id = :aid"? or just an inner join so that an A has to have a b? – Chris Oct 23 '12 at 13:28
  • correct 'p'. I trying to get A class, who have B class in bCollection. or something like this: Select * from A a inner join B b on a.id = b.aid (I need all fields from A and B in A entity or in ArrayList it isn't important) – Terence Oct 23 '12 at 13:52

2 Answers2

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
perissf
  • 15,979
  • 14
  • 80
  • 117
  • Thank's but after that I get Vector who contains a Object[] { A, B} and I don't know what I shall do next; – Terence Oct 24 '12 at 07:09
  • @Terence unfortunately I cannot help you more today, but I am sure you can learn more from the article I've linked. Let me know – perissf Oct 24 '12 at 07:21
  • I use CriteriaQuery cq = cb.createTupleQuery(); ... List result = em.createQuery(q).getResultList(); and all work fine, Thank's. – Terence Oct 25 '12 at 05:39
0

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);
Chris
  • 20,138
  • 2
  • 29
  • 43
  • If I use this, then after inserting a new objects (like this: A a = new A(); em.persist(a); B b = new B(); b.aid = A; em.persist(b);) and then get A fetch B, A bCollection is empty. – Terence Oct 24 '12 at 07:02
  • Yes. You must maintain a's collection of Bs. It's a regular java object, so if you want to see b in there you have to add it or refresh a from the database. Try using em.refresh(a) – Chris Oct 31 '12 at 04:53