Reputation: 1727
I am trying to use criteria queries to perform a join.
My class structure is like this:
@Entity
class Parent {
Intermediate intermediate;
}
@Entity
class Intermediate {
Set<Child> children
}
@Entity
class Child {
String someProperty;
}
I am trying to get all parents where at least one child has a matching property, but cannot work out how to do the joining. If the Intermediate object wasn't there, it would be quite easy:
// Here, Intermediate doesn't exist - Parent has the Set<Child> property
CriteriaBuilder builder = ...
CriteriaQuery<Parent> query = ...
Root<Parent> root = query.from( Parent.class );
Join<Parent, Child> join = root.join( "child" );
Path path = join.get( "someProperty" );
Predicate predicate = builder.equal( path, "somevalue" );
But doing this with the intermediate entity breaks it
CriteriaBuilder builder = ...
CriteriaQuery<Parent> query = ...
Root<Parent> root = query.from( Parent.class );
Join<Parent, Child> join = root.join( "intermediate.child" ); <-- Fails
Caused by: java.lang.IllegalArgumentException: Unable to resolve attribute [intermediate.child] against path
at org.hibernate.ejb.criteria.path.AbstractPathImpl.unknownAttribute(AbstractPathImpl.java:120) ~[hibernate-entitymanager-4.2.0.Final.jar:4.2.0.Final]
at org.hibernate.ejb.criteria.path.AbstractPathImpl.locateAttribute(AbstractPathImpl.java:229) ~[hibernate-entitymanager-4.2.0.Final.jar:4.2.0.Final]
at org.hibernate.ejb.criteria.path.AbstractFromImpl.join(AbstractFromImpl.java:411) ~[hiberna
te-entitymanager-4.2.0.Final.jar:4.2.0.Final]
I can work out the Path object for the child in this example, but JPA doesn't seem to want to let me make a Join using a Path object instead of a Root one.
Can anyone help me please? Thanks
Upvotes: 4
Views: 4550
Reputation: 19543
I think your classes need to be something like this.
@Entity
class Parent {
@OneToOne
Intermediate intermediate;
}
@Entity
class Intermediate {
@OneToOne(mappedBy="intermediate")
Parent parent;
@OneToOne
Set<Child> children
}
@Entity
class Child {
String someProperty;
}
Then you can do the join as it follows.
CriteriaBuilder builder = ...
CriteriaQuery<Parent> query = ...
Root<Parent> root = query.from( Parent.class );
Join<Parent, Child> join = root.join("intermediate").join("children");
Upvotes: 3