有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何在JPA标准中使用投影和where子句?

我有一个人

@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,其中Person的名称是参数

我编写了这个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>)

这怎么正确?我需要元模型类吗


共 (1) 个答案

  1. # 1 楼答案

    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;
    

    及其等价的标准查询:

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