Mam Order
klasę, która ma listę OrderTransactions
i zmapowałem ją za pomocą mapowania Hibernacja jeden do wielu w następujący sposób:
@OneToMany(targetEntity = OrderTransaction.class, cascade = CascadeType.ALL)
public List<OrderTransaction> getOrderTransactions() {
return orderTransactions;
}
Te Order
pola mają również pole orderStatus
, które jest używane do filtrowania według następujących kryteriów:
public List<Order> getOrderForProduct(OrderFilter orderFilter) {
Criteria criteria = getHibernateSession()
.createCriteria(Order.class)
.add(Restrictions.in("orderStatus", orderFilter.getStatusesToShow()));
return criteria.list();
}
To działa, a wynik jest zgodny z oczekiwaniami.
Teraz tutaj jest moje pytanie : Dlaczego, kiedy ustawić typ pobrać bezpośrednio do EAGER
wykonaj Order
s pojawiają się wielokrotnie w otrzymanym liście?
@OneToMany(targetEntity = OrderTransaction.class, fetch = FetchType.EAGER, cascade = CascadeType.ALL)
public List<OrderTransaction> getOrderTransactions() {
return orderTransactions;
}
W jaki sposób musiałbym zmienić kod kryteriów, aby osiągnąć ten sam wynik w nowym ustawieniu?
Odpowiedzi:
Jest to faktycznie oczekiwane zachowanie, jeśli poprawnie zrozumiałem twoją konfigurację.
Otrzymujesz to samo
Order
wystąpienie w każdym z wyników, ale od teraz wykonujesz sprzężenie zOrderTransaction
, musi zwrócić taką samą ilość wyników, jaką zwróci zwykłe sprzężenie sqlW rzeczywistości powinno się to pojawiać wiele razy. wyjaśnia to bardzo dobrze sam autor (Gavin King) tutaj : Obaj wyjaśnia, dlaczego i jak nadal uzyskać wyraźne wyniki
Wspomniane również w FAQ Hibernacji :
źródło
Oprócz tego, o czym wspomniał Eran, innym sposobem uzyskania pożądanego zachowania jest ustawienie transformatora wyników:
źródło
próbować
na przykład
}
źródło
Nie używaj List i ArrayList, ale Set i HashSet.
źródło
Używając Java 8 i strumieni, dodaję w mojej metodzie narzędziowej następującą informację zwrotną:
Strumienie bardzo szybko usuwają duplikaty. W mojej klasie Entity używam adnotacji w następujący sposób:
Myślę, że w mojej aplikacji lepiej jest używać sesji w metodzie, w której potrzebuję danych z bazy danych. Zamknięta sesja, kiedy skończyłem. Oczywiście ustaw moją klasę Entity, aby używała typu pobierania leasy. Idę do refaktoryzacji.
źródło
Mam ten sam problem, aby pobrać 2 powiązane kolekcje: użytkownik ma 2 role (zestaw) i 2 posiłki (lista), a posiłki są zduplikowane.
DISTINCT nie pomaga (zapytanie DATA-JPA):
Nareszcie znalazłem 2 rozwiązania:
Ostateczne rozwiązanie:
źródło
Zamiast używać hacków, takich jak:
Set
zamiastList
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
które nie modyfikują zapytania sql, możemy użyć (cytując specyfikacje JPA)
który nie modyfikuje wynikowego zapytania sql, w ten sposób mając
DISTINCT
w sobie.źródło
Stosowanie zewnętrznego sprzężenia nie wydaje się dobrym zachowaniem i przynosi zduplikowane rezultaty. Jedyne, co pozostało, to filtrowanie naszego wyniku za pomocą strumieni. Dzięki java8 dając łatwiejszy sposób filtrowania.
źródło