Cómo reutilizar un objeto Criteria con Hibernate?
-
21-08-2019 - |
Pregunta
Estoy tratando de hacer la consulta resultado de paginación con Hibernate y displaytag, e Hibernate DetachedCriteria
objetos están haciendo todo lo posible para interponerse en el camino. Me explico ...
La forma más sencilla de hacer la paginación con displaytag parece ser la aplicación de la PaginatedList
interfaz 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 implementación PaginatedList un objeto Criteria y dejar que funcione 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, debido a que el addOrder()
o las llamadas setProjection()
modificar los criterios objeto renderizado en-utilizable para las llamadas sucesivas. No estoy del todo seguro de la orden de las llamadas, pero el PP emite un error en getFullListSize()
tratando de hacer un "select count(*) ... order by ...
", que es obviamente erróneo.
Creo que podría solucionar este problema mediante la creación de un objeto de mi propia para realizar un seguimiento de las condiciones de consulta y reconstruir el objeto Criteria para cada llamada, pero que se siente como reinventar otra rueda. ¿Hay una manera más inteligente, posiblemente, la copia de los criterios inicialmente entraban y trabajan en esa copia?
Actualizar :
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, Criteria
fallará. No tendría sentido para golpear el PP sólo una vez (en count
diría) y almacenar en caché los resultados, sin necesidad de copiar / restablecer el select
objeto, pero aún así ...
Actualizar (de nuevo) : Olvidarse de que, una vez que he hecho la <=> no puedo hacer el <=>, y viceversa. Realmente necesito dos objetos distintos <=>.
Solución
así, DetachedCriteria son Serializable, por lo que se han incorporado (si es poco elegante) el apoyo clon de profundidad. Se podría serializar los criterios iniciales para un byte [] una vez en la construcción, a continuación, deserializar cada vez que desee utilizarlo.
Otros consejos
Criteria.setProjection(null);
Criteria.setResultTransformer(Criteria.ROOT_ENTITY);
Se efectivamente "reset" los criterios entre la proyección y ejecución de rowCount los criterios en sí.
Me asegurarse de que su orden no se ha añadido antes de hacer el rowCount, que va a ralentizar las cosas. Mi aplicación de PaginatedList siempre se ejecuta una consulta recuento antes de buscar resultados, así que pedir no es un problema.
En ese poste vi a un método CriteriaTransformer.clone.
Esto debería copiar el objeto criterios.
También puede configurar la proyección de su método GetList.
Woops no me di cuenta que se está refiriendo a la hibernación java. De todos modos, este http://forum.hibernate.org/viewtopic.php?t=939039
mensaje del foro debe ser capaz de responder a su pregunta.
feo, ya que puede ser que terminé usando el truco de serialización. Yo sólo serializar el objeto DetachedCriteria
a una matriz de bytes en la construcción de la PaginatedList
objeto y de-serializar cuando sea necesario. Ay.
Otra cosa vale la pena probar:
implementar un DAO genérico como el sugerido en el sitio de hibernación y pasarlo a la PaginatedList oponerse, 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 han probado todavía, pero debería funcionar.
public static DetachedCriteria Clone(this DetachedCriteria criteria)
{
var dummy = criteria.ToByteArray();
return dummy.FromByteArray<DetachedCriteria>();
}