Не удается получить несколько пакетов: почему @IndexColumn возвращает неправильные результаты? - PullRequest
1 голос
/ 10 ноября 2011

Ребята, пожалуйста, помогите мне решить следующую проблему.

Я столкнулся со знаменитой ошибкой "невозможно одновременно получить несколько сумок", потому что у меня есть два списка в моей родительской сущности.Вот небольшая часть кода:

class Manager{
    @OneToMany(cascade = CascadeType.ALL)
    @Fetch(FetchMode.JOIN)
    @IndexColumn(name = "id")
    private List<Action> actions;

    @OneToMany(cascade = CascadeType.ALL)
    @Fetch(FetchMode.JOIN)
    @IndexColumn(name = "id")
    private List<Activity> activities;
(...)
}

Отображение является однонаправленным.

ОК, я гуглил, что могу использовать аннотацию IndexColumn, чтобы исправить это.Я реализовал это, как вы видите, и теперь я не получаю упомянутое исключение.Но проблема в том, что теперь, если я хочу получить всех Менеджеров из базы данных, я получаю БОЛЬШЕ экземпляров менеджера, которые действительно существуют!

Например, 9 экземпляров Менеджера, если у меня есть только 1 менеджер и 3 дочерних экземпляра в каждой коллекции.Я могу понять, почему это происходит: Hibernate производит выбор, который выглядит как

select ... from Manager this_ 
left outer join manager_action actions3_ on this_.id=actions3_.Manager_id 
left outer join Action action4_ on actions3_.actions_id=action4_.id 
left outer join Manager_Activity activities5_ on this_.id=activities5_.Manager_id 
left outer join Activity activity6_ on activities5_.activities_id=activity6_.id 

... и он действительно выбирает БОЛЬШЕ строк, чем один.

Почему это происходит?Как я могу это исправить?

1 Ответ

0 голосов
/ 10 ноября 2011

Hibernate делает декартово произведение и в этом случае не дедуплицирует. Подобные этому декартовы произведения (3 действия * 3 действия = 9 строк) хорошо работают только с наборами вместо списков.

Даже с двумя наборами, возможно, вам следует избегать этих видов декартовых произведений. Подумайте об этом: получение только одного менеджера с 100 действиями и 100 действиями позволяет получить 10000 строк из базы данных Возможно, вам следует сделать два запроса:

  • тот, который выбирает менеджера с его действиями (100 строк)
  • тот, который выбирает того же менеджера с его действиями (100 строк)

Это сделало бы только 200 строк вместо 10000. И результат будет таким же, потому что действия будут присоединены к тому же экземпляру Manager в сеансе. Это также поможет избежать проблемы дублирования.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...