【问题标题】:CriteriaAPI get collection sizeCriteria API 获取集合大小
【发布时间】:2012-11-12 12:28:44
【问题描述】:

我有两个实体: 第一人称(桌人);

@Entity
public class Person implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", nullable = false)
    private Integer id;
    @Column(name = "name", nullable = false, length = 2147483647)
    private String name;
    @Column(name = "first_name", nullable = false, length = 2147483647)
    private String firstName;
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "peopleId")
    private List<PeopleEmail> peopleEmailList;

    //... constuctors
    //... getters setters
}

还有 PeopleEmail 类

@Entity
public class PeopleEmail implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", nullable = false)
    private Integer id;
    @NotNull
    @Column(name = "email", nullable = false, length = 2147483647)
    private String email;
    @JoinColumn(name = "people_id", referencedColumnName = "id", nullable = false)
    @ManyToOne(optional = false)
    private Person peopleId;

    //... constuctors
    //... getters setters
}

如您所见,两个实体都处于一对多关系中。 我想创建另一个类:

public class PersonAndCompany{
   private String personName;
   private String companyName;
   private int emailCount;

    //... constuctors
    //... getters setters
}

我想编写 typequery 来填充 PersonAndCompany.class 字段,其中包含人名和 companyName(另一个类)和电子邮件计数,其中人员电子邮件计数超过 2。我想使用条件 api。我写了一些代码,但我不知道如何在 PersonAndCompany.class 中添加条件并填写 emailcount。

CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<PersonAndCompany> cq = cb.createQuery(PersonAndCompany.class);
Root<Person> person = cq.from(Person.class);
Join<Person, Company> company = person.join(Person_.companyId);
cq.where(cb.greaterThan(cb.size(person.get(Person_.peopleEmailList)), 2));

Selection<PersonAndCompany> select = cb.construct(PersonAndCompany.class,
                        person.get(Person_.firstName),
                        company.get(Company_.name));
cq.select(select);
TypedQuery<PersonAndCompany> query = em.createQuery(cq);
return query.getResultList();

【问题讨论】:

    标签: jakarta-ee jpa criteria-api


    【解决方案1】:

    我认为可以在某些 JPA 提供和某些数据库的 select 子句中包含子查询。

    Select p.firstName, c.name, (select count(e) from Email e where e.person = p) from Peron p join p.company c where size(p.emails) > 2
    

    否则,您将需要使用计数和某种分组依据。然后可以将您在 where 子句中的大小检查移到 have 子句中。

    在 JPQL 中类似于,Criteria 是等价的,

    Select p.id, p.firstName, c.name, count(e) from Peron p join p.company c join p.peopleEmaiList e group by p.id, p.firstName, c.name having count(e) > 2
    

    您也可以随时读取对象,然后在 Java 中获取集合的 size()。您可以对电子邮件和公司使用连接或批量提取来避免 n+1 查询。

    【讨论】:

      【解决方案2】:

      当我想获得不同结构的派生或计算值时,我对 TupleQueries 的运气更好,如下所示:

      CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
      CriteriaQuery<Tuple> cq = cb.createTupleQuery(); 
      // add cq.from and joins 
      // add cq.where predicates 
      cq.select( cb.tuple(   
        person.get(Person_.firstName).alias("person"),  
        company.get(Company_.name).alias("company"),  
        // and maybe ...
        cb.size(person.get(Person_.peopleEmailList)).alias("emailcount") );
      // ...
      ...
      TypedQuery<Tuple> typedQuery = getEntityManager().createQuery(cq);
      for(Tuple t : typedQuery.getResultList()) {
        PersonAndCompany ret = new PersonAndCompany();
        ret.setPersonName( t.get("person", String.class) );
        ret.setCompanyName( t.get("company", String.class) );
        ret.setEmailCount( t.get("emailcount", Integer.class) );
      }
      return ret;
      

      希望对您有所帮助。祝你好运;)

      【讨论】:

        猜你喜欢
        • 2010-11-18
        • 2013-12-02
        • 2019-07-06
        • 2015-09-08
        • 1970-01-01
        • 1970-01-01
        • 2011-08-31
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多