10

I guess this is easy, but I can't figure it out.

If I have entities Foo and Bar:

@Entity
class Foo{
   @OneToMany
   List<Bar> bars;
}

@Entity
class Bar{
   @Column
   int data;
}

and if I want to create a Join (javax.persistence.criteria.Join<Foo, Bar>) object, I can do it like this:

Root<Foo> root = ...;
Join<Foo,Bar> join = root.join(Foo_.bars);

But how can I make an inverse join

Join<Bar,Foo> inverseJoin = barRoot.join....()...?

since I don't have a java field in the class Bar that points to it's Foo parent, it is unidirectional relation?

mabi
  • 5,279
  • 2
  • 43
  • 78
  • Well, the obvious answer is: it isn't a unidirectional relationship if you need an inverse join. Have you checked out using a bidirectional relation (adding `@ManyToOne` to `Bar`)? – mabi Nov 03 '14 at 15:30
  • I've considered that, but I would like to avoid that if possible. – Mihajlo Brankovic Nov 03 '14 at 16:13
  • You can probably need to resort to a raw SQL query, then. I don't know of way to do what you want and IMHO there shouldn't be one. – mabi Nov 03 '14 at 17:03
  • Check this answer... Maybe it can help you: http://stackoverflow.com/questions/27939173/criteria-query-for-unidirectional-one-to-many-relationship – andresram1 Feb 19 '16 at 16:42

1 Answers1

-1

If what you need is given a known Bar who is its belonging Foo this would fit. Sentence will not be translated to a SQL JOIN but it is semantically equivalent.

CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Foo> cq = cb.createQuery(Foo.class);

Root<Foo> fooRoot = cq.from(Foo.class);
Root<Bar> barRoot = cq.from(Bar.class);

cq.select(fooRoot);
cq.where(barRoot.in(fooRoot.get("bars")));
Jorge C
  • 478
  • 4
  • 14
  • **barRoot.in** I wonder if it works with **equal** instead of **in** – Yan Khonski Sep 29 '16 at 09:51
  • **fooRoot.get("bars")** is a collection. Using **equal** would try to compare a single element (**barRoot**) to a collection, which is wrong. – Jorge C Oct 03 '16 at 11:33
  • 1
    Won't this create a cartesian product (cross-join, i.e. performance hell)? – Alkanshel Feb 23 '17 at 23:39
  • It all depends on your indexes. If the foreign key column on Bar and the primary key on Foo are indexed (PK always are but FK depends on your database) the performance of the query shouldn't be much worse than a join. – Jorge C Feb 26 '17 at 11:11
  • 1
    This solution is not working (at least for me with Hibernate 5.2.11). I have to replace where clause from `barRoot.in(fooRoot.get("bars"))` to `barRoot.in(fooRoot.joinList("bars"))`. However it generates very suboptimal query with one cross join and two inner joins. For simpler solution without two root objects check answer https://stackoverflow.com/questions/27939173 – user2428804 Apr 06 '18 at 06:37