2012-11-24 23 views
0

我有两个实体: 第一个人(表人);CriteriaAPI获取收藏大小

@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场与人姓名和公司名称(其他类)和电子邮件计数,其中个人电子邮件的数量是大于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(); 

回答

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子句中的大小检查可以转移到having子句中。

在JPQL它会是这样的,标准将是等效的,

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集合的大小()。您可以在电子邮件和公司上使用加入或批量提取来避免n + 1个查询。

0

当我想获得衍生或ionto不同的结构,我有更多的运气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; 

希望帮助。祝你好运;)