使用 CriteriaQuery 使用来自 child 实体的两个字段查询 parent 实体

Query for parent entity using two fields from child entity using CriteriaQuery

拥有以下实体

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;
}

您将如何使用 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')

谢谢

更新: 所以我的错误是,而不是做

Join<Parent, Child> c = p.join("children");
Predicate predicate = builder.or(
     builder.equal( c.get("name"), name1 ),
     builder.equal( c.get("name"), name2 )
);

我在做:

Predicate predicate = builder.or(
     builder.equal( p.join("children").get("name"), name1 ),
     builder.equal( p.join("children").get("name"), name2 )
);

导致与 child table 的 2 个内部联接,每个 p.join 我正在使用

尝试这样的事情:

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();