Tengo una Order
clase que tiene una lista de OrderTransactions
y la asigné con un mapeo de Hibernate de uno a muchos así:
@OneToMany(targetEntity = OrderTransaction.class, cascade = CascadeType.ALL)
public List<OrderTransaction> getOrderTransactions() {
return orderTransactions;
}
Estos Order
mensajes también tienen un campo orderStatus
, que se utiliza para filtrar con los siguientes criterios:
public List<Order> getOrderForProduct(OrderFilter orderFilter) {
Criteria criteria = getHibernateSession()
.createCriteria(Order.class)
.add(Restrictions.in("orderStatus", orderFilter.getStatusesToShow()));
return criteria.list();
}
Esto funciona y el resultado es el esperado.
Ahora, aquí está mi pregunta : ¿Por qué, cuando establezco el tipo de búsqueda explícitamente en EAGER
, aparecen las Order
s varias veces en la lista resultante?
@OneToMany(targetEntity = OrderTransaction.class, fetch = FetchType.EAGER, cascade = CascadeType.ALL)
public List<OrderTransaction> getOrderTransactions() {
return orderTransactions;
}
¿Cómo tendría que cambiar mi código de Criterios para alcanzar el mismo resultado con la nueva configuración?
Respuestas:
Este es realmente el comportamiento esperado si entendí su configuración correctamente.
Obtiene la misma
Order
instancia en cualquiera de los resultados, pero como ahora está haciendo una combinación conOrderTransaction
, debe devolver la misma cantidad de resultados que una combinación SQL regularEntonces, en realidad, debería aparecer varias veces. Esto se explica muy bien por el propio autor (Gavin King) aquí : explica por qué y cómo obtener resultados distintos
También se menciona en las preguntas frecuentes de Hibernate :
fuente
Además de lo mencionado por Eran, otra forma de obtener el comportamiento que desea es configurar el transformador de resultado:
fuente
tratar
por ejemplo
}
fuente
No use List y ArrayList, sino Set y HashSet.
fuente
Usando Java 8 y Streams agrego en mi método de utilidad esta declaración de devolución:
Las secuencias eliminan los duplicados muy rápido. Yo uso la anotación en mi clase Entity así:
Creo que es mejor en mi aplicación usar la sesión en el método donde necesito datos de la base de datos. Cierre la sesión cuando termine. Por supuesto, configuré mi clase Entity para usar el tipo de búsqueda leasy. Voy a refactorizar.
fuente
Tengo el mismo problema para buscar 2 colecciones asociadas: el usuario tiene 2 roles (Conjunto) y 2 comidas (Lista) y las comidas están duplicadas.
DISTINCT no ayuda (consulta DATA-JPA):
Por fin he encontrado 2 soluciones:
Solución final:
fuente
En lugar de usar trucos como:
Set
en vez deList
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
que no modifican su consulta sql, podemos usar (citando especificaciones JPA)
que modifica la consulta sql resultante, por lo que tiene un
DISTINCT
archivo.fuente
No parece un buen comportamiento aplicar una combinación externa y generar resultados duplicados. La única solución que queda es filtrar nuestro resultado usando streams. Gracias java8 por dar una forma más fácil de filtrar.
fuente