Ответ 1
При использовании подобных имен использование отличается.
I. Projections.distinct(Projections.property("id"));
этот оператор будет переведен в SQL Statement. Он будет передан в DB Engine и выполнен как SQL DISTINCT
. См:
т.е. этот пример:
List results = session.createCriteria(Cat.class)
.setProjection( Projections.projectionList()
.add( Projections.distinct(Projections.property("id")) )
)
.list();
будет выглядеть следующим образом:
SELECT DISTINCT(cat_id) FROM cat_table
II. criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
Эта инструкция выполняется ex-post. После возвращения SQL-запроса из механизма БД и Hibernate выполняет итерацию результирующего набора, чтобы преобразовать его в список наших объектов.
Но нужно ли это всегда? НЕТ, в основном это не требуется.
Единственный случай, когда мы ДОЛЖНЫ использовать это, если в запросе есть ассоциация - ВСТУПЛЕНИЕ в конец
one-to-many
.
Так как если у нас есть один cat
и два kittens
, это вернет строки два, а cat
только:
SELECT cat.*, kitten.*
FROM cat_table as cat
INNER JOIN kitten_table kitten ON kitten.cat_id = cat.cat_id
Итак, оператор в конце criteriaQuery
:
... // criteriaQuery joining root and some one-to-many
.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
приведет к списку только с одним котом.