2010-04-12 20 views
5

Tengo una pantalla de búsqueda, usando JSF, JBoss Seam e Hibernate debajo. Hay columnas de A, B y C, donde las relaciones son las siguientes:Hibernar: ordenar múltiples relaciones de uno a muchos

Un (1 < ->) B (1 < ->) C

A tiene una Lista B < > y B tiene una lista < C> (ambas relaciones son uno a muchos).

La tabla de IU admite pedidos por cualquier columna (ASC o DESC), por lo que quiero que se ordenen los resultados de la consulta. Esta es la razón por la que utilicé las Listas en el modelo.

Sin embargo, tengo la excepción de que Hibernate no puede buscar con entusiasmo varias bolsas (considera que ambas listas son bolsas). Hay un interesante blog poste here, e identifican las siguientes soluciones:

  1. Uso @IndexColumn anotación (no hay ninguno en mi base de datos, y lo que es más, quiero que la posición de los resultados que se determina por el orden, no por una columna de índice)
  2. Fetch con pereza (por razones de rendimiento, necesito recuperación temprana)
  3. Lista de cambios a Set

por lo tanto, he cambiado la lista para configurar, que por cierto es más correcto , a nivel de modelo.

  • primer lugar, si no utilice @OrderBy, la PersistentSet devuelto por Hibernate envuelve un HashSet, que no tiene ningún pedido. Entonces, cuando lo repito en la interfaz de usuario, el orden es aleatorio, cualquiera que sea el orden de la base de datos.
  • En segundo lugar, si yo do uso @OrderBy, el PersistentSet ajusta un LinkedHashSet, que tiene orden y es lo que me gustaría. Sin embargo,, la propiedad OrderBy está codificada de forma rígida y tiene prioridad sobre cualquier ordenamiento que establezca tanto usando Colecciones (link) como HQL (link). Como tal, todos los otros pedidos que solicito a través de la interfaz de usuario vienen después.

que intentó de nuevo con conjuntos, y se utiliza SortedSet (y su aplicación, TreeSet), pero tengo algunos problemas:

  1. que quiero que ordenan a tener lugar en el PP, y no en la memoria , que es lo que hace TreeSet (ya sea a través de un Comparador, o a través de la interfaz Comparable de los elementos).
  2. En segundo lugar, encontré que existe la anotación Hibernate @Sort, que tiene SortOrder.UNSORTED y también puede establecer un Comparador. Todavía no he logrado hacerlo compilar, pero todavía no estoy convencido de que sea lo que necesito.

¿Algún consejo?

ACTUALIZACIÓN:

Uno de los requisitos es para la clasificación que tendrá lugar en la base de datos.

Update2:

creado un proyecto Maven sencilla y comprometida como un proyecto Google Code. Este es mi patio de recreo personal para el problema.

Respuesta

3

¿Cuál es el punto de orden en el DB cuando una columna puede reordenar el mismo conjunto de resultados? Si necesita acceder al DB cada vez que hace clic en una columna diferente en la interfaz de usuario, solo crea un problema de rendimiento para usted. Este es exactamente el caso cuando tiene sentido ordenar el conjunto en la memoria.

sobre las bolsas y las listas, esto es lo que la hibernación Bok tiene que decir:

Las bolsas no pueden ser clasificadas (no hay TreeBag, por desgracia), ni podrá listas; el orden de los elementos de la lista está definido por el índice de la lista.

+0

Hola Peter, gracias por la respuesta. Tengo la impresión de que la ordenación (y el filtrado) tienen lugar mucho más rápido en la base de datos, donde también puedes crear tus propios índices. Puedo estar equivocado, por supuesto. Utilizaría la clasificación del servidor (con Java), si quisiera una clasificación muy especializada que sería fácil solo con un Comparador. –

+0

@ Péter Török (+1) Por lo que Hibernate en Acción dijo –

+0

@Markos La ordenación por sí misma se puede hacer más rápido en el DB (especialmente para grandes conjuntos de resultados), pero golpear el DB (casi siempre) tiene una latencia sustancial (excepto tal vez cuando el DB se ejecuta en la misma máquina que su cliente). Por lo general, se pierde más por la latencia de lo que se gana con un pedido más rápido. Por supuesto, no solo me creas, lo mejor es medirlo tú mismo, en tu propia configuración. –

0

Sobre la base de lo que Hibernate en Acción dicho y la solución proporcionada por su propia respuesta, que podría ordenar su colección en tiempo de ejecución a avoit su excepción

@Entity 
public class Aa { 

    private List<Bb> bbList - new ArrayList<Bb>(); 

    @OneToMany 
    public List<Bb> getBbList() { 
     return bbList; 
    } 

    @Transient 
    public List<Bb> getBbListSortedBySomeProperty() { 
     Collections.sort(bbList, new Comparator<Bb>() { 
      public int compare(Bb o1, Bb o2) { 
       return o1.getSomeProperty().compareTo(o2.getSomeProperty()); 
      } 
     }); 

     return bbList; 

    } 

} 

Tenga en cuenta someProperty debe implementar Comparable

...

@Entity 
public class Bb { 

    private List<Cc> ccList - new ArrayList<Cc>(); 

    @OneToMany 
    public List<Cc> getCcList() { 
     return ccList; 
    } 

} 
+0

Hola Arthur, gracias por la respuesta. Sin embargo, quiero que la clasificación tenga lugar en el DB. –

Cuestiones relacionadas