Tengo problemas para representar una jerarquía de objetos en Hibernate. He buscado y no he podido encontrar ningún ejemplo que lo haga o algo similar. Me disculpan si se trata de una pregunta común.Representación eficiente de jerarquías en Hibernate
Tengo dos tipos que me gustaría persistir usando Hibernate: Grupos y Artículos.
* Los grupos se identifican únicamente por una combinación de su nombre y su elemento primario.
* Los grupos están organizados en varios árboles, de modo que cada grupo tiene cero o un grupo principal.
* Cada elemento puede ser miembro de cero o más grupos.
Idealmente, me gustaría una relación bidireccional que permite que consiga:
* todos los Grupos que un artículo es un miembro de
* Todos los artículos que son un miembro de un grupo en particular o sus descendientes.
También necesito poder recorrer el árbol de grupos desde la parte superior para mostrarlo en la interfaz de usuario.
La estructura básica de objetos lo ideal sería tener este aspecto:
Originalmente, que acababa de hacer un simple bidireccional muchos-a-muchos relación entre artículos y grupos, de manera que ir a buscar todos los elementos de una jerarquía del grupo requiere recursión hacia abajo del árbol, y recuperar los grupos de un elemento era un captador simple, es decir:
class Group {
...
private Set<Item> items;
private Set<Group> children;
...
/** @return all items in this group and its descendants */
Set<Item> getAllItems() {
Set<Item> allItems = new HashSet<Item>();
allItems.addAll(this.items);
for(Group child : this.getChildren()) {
allItems.addAll(child.getAllItems());
}
return allItems;
}
/** @return all direct children of this group */
Set<Group> getChildren() {
return this.children;
}
...
}
class Item {
...
private Set<Group> groups;
/** @return all groups that this Item is a direct member of */
Set<Group> getGroups() {
return this.groups;
}
...
}
Sin embargo, esto dio lugar a múltiples peticiones de base de datos para buscar a los elementos de un grupo con muchos descendientes, o para recuperar todo el grupo árbol para mostrar en la interfaz de usuario. Esto parece muy ineficiente, especialmente con árboles grupales más profundos y grandes. ¿Existe alguna forma mejor o estándar de representar esta relación en Hibernate?
¿Estoy haciendo algo obviamente incorrecto o estúpido?
Mi único otro pensamiento hasta el momento era la siguiente: Reemplazar campos id, los padres y el nombre del grupo con un "camino" única cadena que especifica toda la ascendencia de un grupo, por ejemplo:
/rootGroup
/rootGroup/aChild
/rootGroup/aChild/aGrandChild
La tabla de unión entre Grupos y Elementos contendría entonces group_path y item_id.
Esto soluciona inmediatamente los dos problemas que estaba sufriendo anteriormente:
1. Toda la jerarquía de grupos puede extraerse de la base de datos en una sola consulta y reconstruirse en la memoria.
2. Para recuperar todos los elementos de un grupo o de sus descendientes, podemos seleccionar entre group_item donde group_path = 'N' o group_path como 'N /%'
Sin embargo, esto parece derrotar el punto de utilizar Hibernate. Todos los pensamientos bienvenidos!
¿No es la máxima de Knuth "La optimización prematura es la raíz de todos los males?" –
Supongo que, como en varios casos similares, este no es un problema de grandes estructuras de datos en memoria, sino un número creciente de operaciones de SQL. Si bien cada operación es realmente rápida, en redes de objeto complejas, el número de consultas y la latencia de la comunicación generarán una aplicación para rastrear. En este caso, normalmente prefiero identificar partes más grandes de la red y usar técnicas para (pre) buscarlas lo más temprano posible (vea la respuesta adicional a continuación). La memoria puede reutilizarse fácilmente. –
@Mathew Sí, creo que sí dijo eso. @Ralf Simplemente no tenemos la información. Solo estoy tratando de cubrir ambas bases. –