У меня есть Order
класс, у которого есть список, OrderTransactions
и я сопоставил его с отображением Hibernate один-ко-многим следующим образом:
@OneToMany(targetEntity = OrderTransaction.class, cascade = CascadeType.ALL)
public List<OrderTransaction> getOrderTransactions() {
return orderTransactions;
}
У них Order
также есть поле orderStatus
, которое используется для фильтрации по следующим критериям:
public List<Order> getOrderForProduct(OrderFilter orderFilter) {
Criteria criteria = getHibernateSession()
.createCriteria(Order.class)
.add(Restrictions.in("orderStatus", orderFilter.getStatusesToShow()));
return criteria.list();
}
Это работает, и результат ожидаемый.
Теперь вот мой вопрос : почему, когда я явно устанавливаю тип выборки EAGER
, Order
s появляются несколько раз в результирующем списке?
@OneToMany(targetEntity = OrderTransaction.class, fetch = FetchType.EAGER, cascade = CascadeType.ALL)
public List<OrderTransaction> getOrderTransactions() {
return orderTransactions;
}
Как мне изменить код критериев, чтобы достичь того же результата с новой настройкой?
Ответы:
На самом деле это ожидаемое поведение, если я правильно понял вашу конфигурацию.
Вы получаете тот же
Order
экземпляр в любом из результатов, но, поскольку теперь вы выполняете соединение сOrderTransaction
, он должен возвращать такое же количество результатов, которое будет возвращать обычное соединение sqlТак что на самом деле он должен появиться несколько раз. это очень хорошо объясняется самим автором (Гэвином Кингом) здесь : Это объясняет, почему и как по-прежнему получать четкие результаты
Также упоминается в FAQ по Hibernate :
источник
В дополнение к тому, что упомянул Эран, еще один способ получить желаемое поведение - это установить преобразователь результатов:
источник
пытаться
например
}
источник
Не используйте List и ArrayList, а используйте Set и HashSet.
источник
Используя Java 8 и Streams, я добавляю в свой служебный метод следующий статус возврата:
Потоки очень быстро удаляют дубликаты. Я использую аннотацию в своем классе Entity следующим образом:
Я думаю, что в моем приложении лучше использовать сеанс в методе, где мне нужны данные из базы данных. Завершите сеанс, когда я закончу. Конечно, я установил мой класс Entity на использование арендованного типа выборки. Иду на рефакторинг.
источник
У меня такая же проблема с получением 2 связанных коллекций: у пользователя есть 2 роли (Set) и 2 приема пищи (List), а блюда дублируются.
DISTINCT не помогает (запрос DATA-JPA):
Наконец я нашел 2 решения:
Окончательное решение:
источник
Вместо использования таких хаков, как:
Set
вместо тогоList
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
которые не изменяют ваш sql-запрос, мы можем использовать (цитируя спецификации JPA)
который изменяет результирующий запрос sql, таким образом имея
DISTINCT
в нем.источник
Звучит не очень хорошо, применяя внешнее соединение и приводя к повторяющимся результатам. Единственное решение - отфильтровать наш результат с помощью потоков. Спасибо java8 за упрощение фильтрации.
источник