Критерии .DISTINCT_ROOT_ENTITY против Projections.distinct

Я новичок в Hibernate. Я узнал, что мы можем получить отличный результат, используя два разных способа. Может ли кто-нибудь сказать мне, в чем разница между ними? Когда использовать один над другим?

Projections.distinct(Projections.property("id"));

против

criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

Ответ 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)

приведет к списку только с одним котом.

Ответ 2

Из документов: DISTINCT_ROOT_ENTITY Каждая строка результатов является отдельным экземпляром корневого объекта

distinct() выбирает разное по свойству, в вашем случае по идентификатору