我有实体人
@Entity(name = "Person")
public class Person {
@Id
@GeneratedValue
private Long id;
private String name;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "person")
private Set<Phone> phones=new HashSet<Phone>();
public Person() {
}
public Person(String name) {
this.name = name;
}
广告实体电话 :
@Entity(name = "Phone")
public class Phone {
@Id
@GeneratedValue
private Long id;
@Column(name = "`number`")
private String number;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "person_id", nullable = false)
private Person person;
public Phone() {
}
它们具有一对多的关系。现在我想在jpa标准中构建这样的查询:
select p.phones from person p join phone ph where p.name = :name;
所以我想从人名是参数的 Person 实体中提取Set<Phone> phones
。
我写了这个jpa标准查询:
CriteriaBuilder builder = session.getCriteriaBuilder();
CriteriaQuery<Person> query = builder.createQuery(Person.class);
Root<Person> root = query.from(Person.class);
CriteriaQuery<Person> where = query.where(builder.equal(root.get("name"), "Mary Dick"));
CompoundSelection<Set> projection = builder.construct(Set.class, root.get("phones"));
where.select(projection); //compile error: The method select(Selection<? extends Person>) in the type CriteriaQuery<Person> is not applicable for the arguments (CompoundSelection<Set>)
}
但它给出了编译错误:
The method select(Selection<? extends Person>) in the type CriteriaQuery<Person> is not applicable for the arguments (CompoundSelection<Set>)
怎么对?我需要元模型类吗?
CompoundSelection<Y> construct(Class<Y> result, Selection<?>... terms)
仅当查询涉及某些投影时,此方法才有用,这些投影未完全由单个实体类封装。如果是这种情况,第一个参数将是自定义 POJO 类(具有合适的构造函数(,其字段对应于查询的 select 子句。
在这种情况下,所选内容已经是实体类的一部分。因此,您可以简单地选择所需的字段。
CriteriaQuery<Person> query = builder.createQuery(Person.class);
Root<Person> root = query.from(Person.class);
query.where(builder.equal(root.get("name"), "Mary Dick"));
query.select(root.get("phones"));
上面的查询将返回人员列表。但是,如果您只查找可迭代的手机列表,请尝试使用稍微不同的查询。
select ph from phone ph join ph.person p where p.name = :name;
及其等效的 CriteriaQuery:
CriteriaBuilder builder = session.getCriteriaBuilder();
CriteriaQuery<Phone> query = builder.createQuery(Phone.class);
Root<Phone> root = query.from(Phone.class);
Join<Phone, Person> join = root.join(root.get("person"))
query.where(builder.equal(join.get("name"), "Mary Dick"));