Having the below entities
class Parent {
@Id
Long id;
String name;
@OneToMany
@JoinColumn(name="parent_fk")
List<Child> children;
}
class Child {
@Id
Long id;
String sex; //male, female
String name;
}
How would you construct the following query using CriteriaBuilder?
SELECT * FROM Parent p JOIN Child c ON p.id = c.parent_fk WHERE c.sex='male' AND (c.name = 'Tom' OR c.name='Jim')
Thank you
update: So my mistake was that instead of doing
Join<Parent, Child> c = p.join("children");
Predicate predicate = builder.or(
builder.equal( c.get("name"), name1 ),
builder.equal( c.get("name"), name2 )
);
I was doing:
Predicate predicate = builder.or(
builder.equal( p.join("children").get("name"), name1 ),
builder.equal( p.join("children").get("name"), name2 )
);
Which was causing 2 inner joins with the child table, one for each p.join i was using
Try something like this:
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<Parent> criteria = builder.createQuery(Parent.class);
Root<Parent> p = criteria.from(Parent.class);
Join<Parent, Child> c = p.join("children");
criteria.select(p);
ParameterExpression<String> name1 = builder.parameter( String.class );
ParameterExpression<String> name2 = builder.parameter( String.class );
ParameterExpression<String> sex = builder.parameter( String.class );
Predicate predicate = builder.or(
builder.equal( c.get("name"), name1 ),
builder.equal( c.get("name"), name2 )
);
predicate = builder.and(
builder.equal( c.get("sex"), sex ),
predicate
);
criteria.where(predicate);
List<Parent> result = entityManager.createQuery( criteria )
.setParameter( name1, "Tom" )
.setParameter( name2, "Jim" )
.setParameter( sex, "male" )
.getResultList();