Дочерняя коллекция Hibernate ограничена при использовании левого соединения в критериях

При использовании критериев гибернации простое изменение типа соединения влияет на результаты дочерних коллекций корневого класса домена.

Например, наличие у класса Parent отношения «один ко многим» с классом Child со следующими данными:

Parent 
| id | Name     |
|  1 | Parent 1 |

Child
| id | parent_id | Name   |
|  1 |         1 | Child1 |
|  2 |         1 | Child2 |

Использование следующих критериев гибернации возвращает 1 родительскую строку, а доступ к дочерней коллекции приводит к возвращению двух строк:

session.createCriteria(Parent.class)
    .createCriteria('child', CriteriaSpecification.INNER_JOIN)
    .add( Restrictions.eq( 'name', 'Child1' ) )
    .list()

Однако при изменении приведенного выше кода с помощью левого соединения возвращается 1 родительская строка, но при доступе к дочерней коллекции возвращается только соответствующая дочерняя строка.

session.createCriteria(Parent.class)
    .createCriteria('child', CriteriaSpecification.LEFT_JOIN)
    .add( Restrictions.eq( 'name', 'Child1' ) )
    .list()

Почему возникает этот побочный эффект? Я нашел несколько дискуссий об использовании или избежании этого побочного эффекта в зависимости от вашего предполагаемого результата, но ничего не о том, почему он вообще существует и был ли он предназначен. Ближайший прямой вопрос - это старый устаревший дефект (http://opensource.atlassian.com/projects/hibernate/browse/HHH-3872).

  • РЕДАКТИРОВАТЬ 3/24: фиксированные данные *

person michaelcameron    schedule 24.01.2011    source источник
comment
Приятель, все мои знания подсказывают мне, что внутреннее соединение должно получать только одну строку. Я думаю, у вас здесь что-то происходит. Я добавлю это в закладки, чтобы следить за тем, что мне не хватает. Если да, то буду вам очень благодарен.   -  person Satadru Biswas    schedule 19.03.2011
comment
Неправильный ли родительский идентификатор на Child2? Это должно было быть 1?   -  person MikelRascher    schedule 22.03.2011
comment
@MikelRascher - Да, родительский идентификатор Child2 был неправильным. Я исправил это сейчас.   -  person michaelcameron    schedule 24.03.2011


Ответы (2)


Эта проблема описана здесь и, кажется, исправлена ​​в Hibernate 3.6.

https://hibernate.onjira.com//browse/HHH-2049

person Alejandro    schedule 11.07.2011

Я пробовал это: при выполнении этого запроса и последующем вызове parent.getChildren () тогда:

  • LEFT JOIN: выполняется один запрос, содержащий родительский и один соответствующий дочерний, при вызове getChildren () последующие запросы не выполняются.
  • INNER_JOIN: выполняется 2 запроса: один для поиска родителей с соответствующими дочерними элементами, а другой при вызове getChildren ()

Таким образом, кажется, что при вызове LEFT_JOIN дочерние элементы (в данном случае совпадающие дочерние элементы) извлекаются ОЧЕНЬ СЛОВНО, а дочерняя коллекция родительского элемента уже заполнена. Однако для INNER_JOIN эта коллекция помечена как прокси и инициализируется при вызове getChildren (); этот второй запрос, конечно, больше не будет принимать во внимание ограничение на имя и будет просто извлекать всех дочерних элементов для Родителя.

Похоже, что это происходит «внутри» спящего режима, то есть тип соединения влияет на то, как спящий режим обрабатывает результаты. Хотя сгенерированный SQL между левым и внутренним соединением немного отличается (в моем тесте parent.id и child.id были дважды в предложении select), результаты, возвращаемые при запуске SQL в браузере БД, одинаковы.

У меня недостаточно опыта, чтобы определить, является ли это ошибкой или нет, но мне не кажется, что это так.

person Stijn Geukens    schedule 22.03.2011