java - son - imagenes de animales que hibernan
¿Cómo reutilizar un objeto Criteria con hibernación? (6)
Estoy tratando de hacer una consulta de paginación de resultados con hibernación y etiqueta de visualización, y los objetos de Hibernate DetachedCriteria
están haciendo todo lo posible para interponerse en el camino. Dejame explicar...
La forma más fácil de hacer paginación con displaytag es implementar 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 lanzar mi implementación PaginatedList a un objeto Criteria y dejar que funcione a lo largo de estas líneas ...
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 las addOrder()
o setProjection()
modifican el objeto de criterio haciéndolo inutilizable para las llamadas sucesivas. No estoy del todo seguro del orden de las llamadas, pero el getFullListSize()
db arroja un error en getFullListSize()
tratando de hacer un " select count(*) ... order by ...
", lo cual es obviamente incorrecto.
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 haya pasado un pedido, getFullListSize
fallará. Tendría sentido pulsar el getList
db solo una vez (en getList
diría) y almacenar en caché los resultados, sin necesidad de copiar / restablecer el objeto Criteria
, pero aún así ...
Actualización (nuevamente) : Olvídate de eso, una vez que haya hecho el count
no puedo hacer la select
, y viceversa. Realmente necesito dos objetos Criteria
distintos.
Otra cosa que vale la pena intentar:
implementar un DAO genérico como el sugerido en el sitio de hibernate y pasarlo al objeto PaginatedList, junto con un objeto Restrictions. El objeto PaginatedList haría algo así como
Criteria.forClass(myDAO.getPersistentClass())
.add(myRestrictions)
.addOrder(<someOrder>)
y
Criteria.forClass(myDAO.getPersistentClass())
.add(myRestrictions)
.setProjection(Projections.rowCount());
Todavía no lo he intentado, pero debería funcionar.
Por feo que sea, terminé usando el truco de serialización. Solo serializo el objeto DetachedCriteria
a una matriz de bytes en la construcción del objeto PaginatedList
y lo PaginatedList
cuando sea necesario. Ay.
bueno, DetachedCriteria es Serializable, por lo que tienes integrado (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.
En esa publicación, descubrí un método CriteriaTransformer.clone.
Eso debería copiar el objeto de criterio.
También puede establecer la proyección en su método getlist.
Vaya, no noté que te refieres a java hibernate. De todos modos, este http://forum.hibernate.org/viewtopic.php?t=939039
la publicación en el foro debe poder responder a su pregunta.
Criteria.setProjection(null);
Criteria.setResultTransformer(Criteria.ROOT_ENTITY);
Efectivamente "reiniciará" los criterios entre la proyección rowCount y la ejecución de los criterios en sí.
Me aseguraría de que tu pedido no se haya agregado antes de hacer el rowCount, se ralentizarán las cosas. Mi implementación de PaginatedList SIEMPRE ejecuta una consulta de recuento antes de buscar resultados, por lo que ordenar no es un problema.
public static DetachedCriteria Clone(this DetachedCriteria criteria)
{
var dummy = criteria.ToByteArray();
return dummy.FromByteArray<DetachedCriteria>();
}