2008-12-15 10 views
26

Estoy tratando de hacer una consulta de paginación de resultados con hibernación y displaytag, y los objetos Hibernate DetachedCriteria están haciendo su mejor esfuerzo para interponerse en el camino. Me explico ...¿Cómo reutilizar un objeto Criteria con hibernación?

La manera más fácil de hacer con la paginación displaytag parece estar implementando la interfaz PaginatedList que tiene, entre otros, los siguientes métodos:

/* Gets the total number of results. */ 
int getFullListSize(); 

/* Gets the current page of results. */ 
List getList(); 

/* Gets the page size. */ 
int getObjectsPerPage(); 

/* Gets the current page number. */ 
int getPageNumber(); 

/* Get the sorting column and direction */ 
String getSortCriterion(); 
SortOrderEnum getSortDirection(); 

estoy pensando en tirar mi PaginatedList la implementación de un objeto Criteria y dejar actuar a lo largo de las líneas theese ...

getFullListSize() { 
    criteria.setProjection(Projections.rowCount()); 
    return ((Long) criteria.uniqueResult()).intValue(); 
} 

getList() { 
    if (getSortDirection() == SortOrderEnum.ASCENDING) { 
     criteria.addOrder(Order.asc(getSortCriterion()); 
    } else if (getSortDirection() == SortOrderEnum.DECENDING) { 
     criteria.addOrder(Order.desc(getSortCriterion()); 
    } 
    return criteria.list((getPageNumber() - 1) * getObjectsPerPage(), 
         getObjectsPerPage()); 
} 

Pero esto no funciona, porque los addOrder() o las llamadas setProjection() modificar los criterios objeto que lo hacen i n-utilizable para las llamadas sucesivas. No estoy del todo seguro del orden de las llamadas, pero el archivo db arroja un error en getFullListSize() tratando de hacer un "select count(*) ... order by ..." que obviamente está mal.

Creo que podría solucionar esto creando un objeto propio para realizar un seguimiento de las condiciones de la consulta y reconstruir el objeto Criteria para cada llamada, pero parece reinventar otra rueda. ¿Hay alguna manera más inteligente, posiblemente copiando los Criterios que inicialmente pasaron y trabajando en esa copia?

actualización: Parece que getList se llama primero, y getFullListSize se llama varias veces después, por lo que, tan pronto como hay una ordenación aprobada en, getFullListSize fallará. No tendría sentido para golpear el PP sólo una vez (en getList diría) y almacenar en caché los resultados, sin necesidad de copiar/restaurar el objeto Criteria, pero aún así ...

actualización (de nuevo): Olvídate de eso, una vez que he hecho el count no puedo hacer el select, y viceversa. Realmente necesito dos objetos distintos Criteria.

Respuesta

2

bien, DetachedCriteria se pueden serializar, por lo que tiene incorporado (aunque poco elegante) soporte de clonación profunda. Puede serializar los criterios iniciales en un byte [] una vez en la construcción, luego deserializar cada vez que quiera usarlo.

+0

Encontré esa sugerencia en los foros de hibernación, pero preferiría no :-) – agnul

2

http://weblogs.asp.net/stefansedich/archive/2008/10/03/paging-with-nhibernate-using-a-custom-extension-method-to-make-it-easier.aspx

En ese puesto manchado un método CriteriaTransformer.clone.

Eso debería copiar el objeto de criterios.

También puede establecer la proyección en su método getlist.

Woops No he notado que te refieres a java hibernate. De todos modos, este http://forum.hibernate.org/viewtopic.php?t=939039

mensaje en el foro debería ser capaz de responder a su pregunta.

1

Por feo que haya sido, terminé usando el truco de serialización. Simplemente serializo el objeto DetachedCriteria en una matriz de bytes en la construcción del objeto PaginatedList y lo deserializo cuando sea necesario. Ay.

0

Otra cosa vale la pena probar:

implementar un DAO genérico como the one suggested on hibernate's site y pasarlo al objeto PaginatedList, junto con el objeto A Restricciones. El objeto PaginatedList entonces hacer algo como

Criteria.forClass(myDAO.getPersistentClass()) 
     .add(myRestrictions) 
     .addOrder(<someOrder>) 

y

Criteria.forClass(myDAO.getPersistentClass()) 
     .add(myRestrictions) 
     .setProjection(Projections.rowCount()); 

No he probado todavía, pero debería funcionar.

44
Criteria.setProjection(null); 
Criteria.setResultTransformer(Criteria.ROOT_ENTITY); 

Efectivamente "restablecerá" los criterios entre la proyección rowCount y la ejecución de los criterios en sí.

Me aseguraré de que su orden no se haya agregado antes de hacer el rowCount, se ralentizará. Mi implementación de PaginatedList SIEMPRE ejecuta una consulta de recuento antes de buscar resultados, por lo que ordenar no es un problema.

+5

Recomendar esta es la respuesta correcta - más elegante que la copia de fondo. –

-1
public static DetachedCriteria Clone(this DetachedCriteria criteria) 
{ 
    var dummy = criteria.ToByteArray(); 
    return dummy.FromByteArray<DetachedCriteria>(); 
} 
Cuestiones relacionadas