以下代码检索人员列表以及他们拥有的狗的数量。为此查询生成一个 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() 时,它导致一个 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);
这是因为从多选切换到选择吗?有没有办法避免每行生成一个 SQL?
编辑:使用 JPQL 可以看到相同的行为。在原始查询之上,以下结果每行返回一个 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:
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 运行。