3

次のコードは、Person のリストと、所有している犬の数を取得します。このクエリに対して 1 つの SQL が生成されます。

CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Tuple> query = cb.createTupleQuery();
Root<Person> person = query.from(Person.class);
SetJoin<Person,Dog> dogsJoin = person.join("dogs", JoinType.LEFT);
query.multiselect(
        cb.count(dogsJoin.get("id")).alias("numDogs"),
        person.alias("person")
).groupBy(person);

ただし、同じクエリを CriteriaBuilder.construct() を使用するように変換すると、1 つの SQL で生成された PER ROW が返されました。

CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<CountableEntryDto> query = cb.createQuery(CountableEntryDto.class);
Root<Person> person = query.from(Person.class);
SetJoin<Person,Dog> dogsJoin = person.join("dogs", JoinType.LEFT);
query.select(
    cb.construct(CountableEntryDto.class,
                 person,
                 cb.count(dogsJoin.get("id")))
).groupBy(person);

これは、複数選択から選択への切り替えによるものですか? 行ごとに 1 つの SQL が生成されるのを避ける方法はありますか?

編集: JPQL を使用しても同じ動作が見られます。次の結果は、元のクエリに加えて、行ごとに 1 つの SQL が返されます。

List resultList = em.createQuery("select new com.example.dto.CountableEntryDto(p, count(dogs)) from Person p left join p.dogs dogs group by p.id").getResultList();

結果は 4 つの SQL ステートメントになります (3 つの Person エンティティが結果リストに返されます)。

select person0_.id as col_0_0_, count(dogs1_.id) as col_1_0_ from Person person0_ left outer join Dog dogs1_ on person0_.id=dogs1_.owner_id group by person0_.id
select person0_.id as id32_0_, person0_.age as age32_0_, person0_.firstname as firstname32_0_, person0_.lastname as lastname32_0_ from Person person0_ where person0_.id=?
select person0_.id as id32_0_, person0_.age as age32_0_, person0_.firstname as firstname32_0_, person0_.lastname as lastname32_0_ from Person person0_ where person0_.id=?
select person0_.id as id32_0_, person0_.age as age32_0_, person0_.firstname as firstname32_0_, person0_.lastname as lastname32_0_ from Person person0_ where person0_.id=?

でもこれは:

List resultList = em.createQuery("select p, count(dogs) from Person p left join p.dogs dogs group by p.id").getResultList();

実行される SQL は 1 つだけです。

select person0_.id as col_0_0_, count(dogs1_.id) as col_1_0_, person0_.id as id10_, person0_.age as age10_, person0_.firstname as firstname10_, person0_.lastname as lastname10_ from Person person0_ left outer join Dog dogs1_ on person0_.id=dogs1_.owner_id group by person0_.id

Hibernate 4.1.0.Final、Hibernate JPA2 1.0.1.Final を使用しており、Postgres に対して実行しています。

4

0 に答える 0