0

私は 2 つのエンティティを持っています。

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

ご覧のとおり、両方のエンティティが 1 対多の関係にあります。別のクラスを作成したい:

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

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

そして、PersonAndCompany.class フィールドに個人名と companyName (別のクラス) と電子メール数を入力する typequery を書きたいと思います。ここで、個人の電子メールの数は 2 を超えています。基準 API を使用したいと思います。私はいくつかのコードを書いていますが、PersonAndCompany.class に条件 where を追加して 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();
4

2 に答える 2

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 でコレクションの size() を取得することもできます。n+1 クエリを回避するために、電子メールと会社で結合またはバッチ フェッチを使用できます。

于 2012-11-26T14:23:04.543 に答える
0

派生または計算された値を別の構造に取得したいときは、次のように 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;

それが役立つことを願っています。幸運を ;)

于 2014-07-16T13:15:28.163 に答える