corriendo · fotografiando · programando
hibernate
Parte I – Criteria por fechas con hibernate
Feb 14
Cuando nos encontremos en el caso de quere filtrar en nuestra base datos, encontrando aquellos registros que estén dentro de un intervalo definido entre dos fechas y a partir de una fecha de operación, utilizando para ello la interface Criteria de hibernate.
Nuestro método, de búsqueda, tendrá como parámetro de entrada una fecha de Operación y en nuestra tabla de base de datos, tendremos que tener como atributos de la tabla, una fecha de alta y una fecha de baja, la cual puede ser null, además restringiremos la búsqueda a un número de registros dado, para, por ejemplo, realizar una paginación, también podremos agregar un orden o si lo requiere, añadir más filtros de búsqueda por otros parámetros.
En nuestro ejemplo, la EntidadEjemploImpl, es la implementación de la interface EntidadEjemplo, la cuál, será la que está mapeada en los archivos .hbm, de hibernate, estos archivos son los que usará hibernate para relacionar las tablas de base de datos, con las entidades o Pojos.
Iré añadiendo comentarios a las líneas y comentando lo que considere más importante.
Nuestra entidad y su implementación, tendrán el siguiente aspecto:
public class EntidadEjemploImpl implements EntidadEjemplo {
}
public class EntidadEjemplo {
private Date fechaAlta;
private Date fechaBaja;
/*Faltarían los respectivos métodos getter y setter de los atributos.*/
}
Y el código del método de búsqueda, de nuestra clase, aunque existen muchos patrones, lo lógico es que este método fuera implementado en la implementación de un Dao .
/**
* Obtiene las entidades ejemplo en funcion una fecha de operación.
* Devolverá los resultados paginados.
* @param fechaOperacion Date
* @param maxNumRegistrosPorPagina Integer
* @param registroComienzo Integer
* @return Collection
*/
public java.util.Collection findEntidadEjemploByCriteria(
final java.util.Date fechaOperacion,
final java.lang.Integer maxNumRegistrosPorPagina,
final java.lang.Integer registroComienzo) {
try {
//Creamos Criteria de hibernate
// para obtener sólo entidades distintas, añadiremos la opción:
//Criteria.DISTINCT_ROOT_ENTITY
Criteria criterioNuevo =
getSession().createCriteria(EntidadEjemploImpl.class)
.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
/*En muchas ocasiones, sólo tendremos fechas simples, es decir,
sólo con año/mes/día. Para evitarnos problemas, en esos casos,
eliminaremos los milisegundos, segundos, minutos y horas a la
fecha, existen muchas formas de hacer esto, esta es sólo un
ejemplo.
*/
//comprobamos que no sea null, evitando un NullPointerException
if (null != fechaOperacion) {
//formateamos la fecha.
GregorianCalendar fechaOperacionCalendar
= new GregorianCalendar();
fechaOperacionCalendar.setGregorianChange(fechaOperacion);
fechaOperacionCalendar.set(GregorianCalendar.HOUR,0);
fechaOperacionCalendar.set(GregorianCalendar.MINUTE,0);
fechaOperacionCalendar.set(GregorianCalendar.SECOND,0);
fechaOperacionCalendar.set(GregorianCalendar.MILLISECOND,0);
/* Creamos la primera expresión.
Crearemos una restricción usando Restrictions de hibernate:
Esta clase, nos permite ir creando restricciones que se
añadirán a la consulta, en forma de AND, OR, is null, is not null
o comparaciones del tipo , mayor que, menor...
En nuestro caso:
si la fechaAlta no es null: Restrictions.isNotNull("fechaAlta")
y: Restrictions.and(...)
la fecha de alta es mayor o igual que la fecha de Operación:
Restrictions.ge("fechaAlta",fechaOperacionCalendar.getGregorianChange())
*/
LogicalExpression uno =
Restrictions.and(Restrictions.isNotNull("fechaAlta"),
Restrictions.ge("fechaAlta",fechaOperacionCalendar.getGregorianChange()));
/*Esta expresión dará a lugar en la select agregando un AND seguido de:
(entidadEjemplo.fechaAlta is not null AND entidadEjemplo.fechaAlta >=?)
donde ? será el valor de la fechaOperacion.
*/
/*Creamos la segunda expresión, procediendo de igual forma, con fechaBaja:
si la fechaBaja no es null: Restrictions.isNotNull("fechaBaja")
y: Restrictions.and(...)
la fecha de baja es menor que la fecha de Operación:
Restrictions.lt("fechaBaja",fechaOperacionCalendar.getGregorianChange())
*/
LogicalExpression expresionFechasBaja =
Restrictions.and(Restrictions.isNotNull("fechaBaja"),
Restrictions.lt("fechaBaja",fechaOperacionCalendar.getGregorianChange()));
// Dando lugar en la select a otro AND:
(entidadEjemplo.fechaBaja is not null AND entidadEjemplo.fechaBaja <?)
donde ? será el valor de la fechaOperacion.
Como hemos dicho, para el caso de la fecha de Baja, podemos tener
que sea null, por tanto, tendremos que controlarlo y realizar ajustar
la select para este caso. Para ello, añadiremos un OR a la fechaBaja,
para que nos devuelva resultados para el caso que la fechaBaja sea
null o cumpla con la expresionFechasBaja realizada anteriormente
*/
LogicalExpression dos =
Restrictions.or(Restrictions.isNull("fechaBaja"),expresionFechasBaja);
/* Dando lugar en la select a:
(entidadEjemplo.fechaBaja is null OR
(entidadEjemplo.fechaBaja is not null AND entidadEjemplo.fechaBaja <?)
)
donde ? será el valor de la fechaOperacion.
*/
// Tan sólo nos quedará anidar todas las restricciones en un AND y añadirlas al
// criteria de búsqueda creado inicialmente.
criterioNuevo.add(Restrictions.and(uno,dos));
}
//en el caso que queramos traernos sólo un número de resultados.
if (null != maxNumRegistrosPorPagina) {
criterioNuevo.setMaxResults(maxNumRegistrosPorPagina.intValue());
}
//si estamos paginando, además tendremos que decir en que registro comenzamos.
if (null != maxNumRegistrosPorPagina) {
criterioNuevo.setFirstResult(registroComienzo.intValue());
}
//el ejecutar el list() del Criteria, nos devolverá una Collection de las Entidades que estamos buscando.
return criterioNuevo.list();
}
catch (org.hibernate.HibernateException ex) {
/*Podemos tratar la exception de hibernate o cualquier otra, incluso encapsularla,
/ dentro de una exception de nuestra aplicación.*/
throw super.convertHibernateAccessException(ex);
}
}
Con el plugin de code, al ser tan largo y con tabulaciones, queda un poco descolocado ![]()
Referencias:
En una segunda parte, veremos como realizar el filtro no sólo por una fecha de Operación, sino, por dos fechas, una fecha de inicio y una fecha de fin, lo cuál aumenta las posibilidades de búsqueda, así como, el número de registros.
Espero que os sea tan útil, la razón de ponerlo ha sido que existe poca documentación sobre este tema, al menos en español, o quizás no busqué bien
. Seguro que hay algún error, pero en estos momentos no lo veo, jiji.
Nos leemos