Reputation: 6958
Let's say I have two JPA entities:
@Entity
public class EntityA {
@Id
private String id;
@OneToMany
private List<EntityB> b;
...
}
@Entity
public class EntityB {
@Id
private String id;
...
}
What I would like to accomplish is to define a @NamedQuery
that retrieves all EntityB
instances that are not referenced from any EntityA
.
Naively, I would have tried
@NamedQuery(name = "EntityB.findAllUnassigned", query = "SELECT b FROM EntityB b WHERE NOT b IN (SELECT DISTINCT a.b FROM EntityA a)")
but this ends up generating invalid SQL:
select b0_.id as id1_, b0_.attr, ... from b b0_ where b0_.id not in (select distinct . from a a1_, a_b ab2_, b b3_ where a1_.id=ab2_.a_id and ab2_.b_id=b3_.id)
Any alternatives?
Upvotes: 3
Views: 2160
Reputation: 9443
Weird that this query does not give you an exception. But your b.a reference is not legal in this way; you cannot select the collection itself, you want/need to select the collection elements.
SELECT b FROM EntityB b WHERE b NOT IN (SELECT DISTINCT elements(a.b) FROM EntityA a)
Note however that elements is a Hibernate HQL construct, not JPA.
If you care about JPA portability:
SELECT b FROM EntityB b WHERE b NOT IN (SELECT DISTINCT b2 FROM EntityA a join a.b b2)
* NOT IN is the more normal form, so I used that here as well
Upvotes: 6
Reputation: 3059
The EntityB doesn't know about which EntityA it belongs to. There might be some obscure or even some intuitive way of doing what you want to do in JPQL. But from my point of view you have failed to model your object model if you want to ask such questions.
"Hey B, what is your A - or is it non-exitent" Will get answered by: "What is "A"".
Adding information about its apparent relationship to A in B, will quickly resolve your current design problem.
Upvotes: 0
Reputation: 6738
Please try this,
SELECT DISTINCT b FROM EntityB AS b JOIN b.a AS a WHERE a IS NULL
If you can't, try that
SELECT DISTINCT b FROM EntityB AS b JOIN b.a AS a WHERE a.id IS NULL
Upvotes: 0
Reputation: 5399
what do you mean by invalid SQL?
did you actually try ...WHERE b NOT IN...
(note the position of the NOT changed)
Upvotes: 0