2012-05-06 11 views
12

Im creando un criterio de hibernación que verificará si un contrato es/ha sido válido durante un año. El contrato tiene una fecha de inicio y finalización como un campo de fecha estándar.Extracción de criterios de Hibernate Año a partir de la fecha

Así está utilizando para SQL Server, yo creo que algo en las líneas de este SQL:

SELECT * FROM CONTRACT WHERE YEAR(startDate) <= ? AND YEAR(endDate) >= ? 

El signo de interrogación es el año dada como un entero.

Entonces, ¿cómo transformar esto en un criterio de hibernación?

int year = 2011; //Just a testyear for example purposes. 
DetachedCriteria criteria = DetachedCriteria.forClass(Contract.class) 
    .add(Restrictions.le("startDate", year)) 
    .add(Restrictions.ge("endDate", year)); 

Como se puede ver, me falta la parte en la que puedo convertir la fecha de un año para que pueda ser comparado. Naturalmente, mi código no se ejecuta como es.

¿Alguna sugerencia sobre cómo obtener los resultados deseados?

Respuesta

13

que parezca que la API no admite directamente lo que quería, pero no hay solución que usted podría considerar.

Solución 1:

DetachedCriteria criteria = DetachedCriteria.forClass(Contract.class) 
    .add(Restrictions.le("startDate", toEndOfYear(year)) 
    .add(Restrictions.ge("endDate", toStartOfYear(year))); 

public Date toStartOfYear(int year) { 
    Calendar calendar = Calendar.getInstance(); 
    calendar.set(Calendar.YEAR, year); 
    calendar.set(Calendar.DAY_OF_YEAR, 0); 
    calendar.set(Calendar.HOUR_OF_DAY, 0); 
    calendar.set(Calendar.MINUTE, 0); 
    calendar.set(Calendar.SECOND, 0); 
    return calendar.getTime(); 
} 

public Date toEndOfYear(int year) { 
    Calendar calendar = Calendar.getInstance(); 
    calendar.set(Calendar.YEAR, year); 
    calendar.set(Calendar.DAY_OF_YEAR, 0); 
    calendar.set(Calendar.HOUR_OF_DAY, 0); 
    calendar.set(Calendar.MINUTE, 0); 
    calendar.set(Calendar.SECOND,-1); 
    return calendar.getTime(); 
} 

Ejemplo de salida de los dos métodos:

System.out.println(toStartOfYear(2013)); 
System.out.println(toEndOfYear(2013)); 

Mon Dec 31 00:00:00 MYT 2012 
Sun Dec 30 23:59:59 MYT 2012 

Solución 2:

DetachedCriteria criteria = DetachedCriteria.forClass(Contract.class) 
    .add(Restrictions.sqlRestriction("YEAR(startDate) >= ? ", year,Hibernate.INTEGER)) 
    .add(Restrictions.sqlRestriction("YEAR(endDate) <= ? ", year,Hibernate.INTEGER)); 
+1

Solución 1 es una buena alternativa limpia, aunque el método 'toEndOfYear' debe sumar 1 al año como pasó a 'cal.set', de lo contrario obtendrá el final del año anterior – Numeron

5

Uso Restrictions.sqlRestriction que va a resolver su problema

3

Si utiliza JPA criteriaBuilder, puede usa el criteriaBuilder.function método. P.ej.

contractRepository.findAll(new Specification<Contract>() { 
    @Override 
    public Predicate toPredicate(Root<Contract> root, CriteriaQuery<?> query, CriteriaBuilder cb) { 
    return cb.ge(cb.function("year", Integer.class, root.get(Contract_.endDate)), year); 
    } 
}); 

(I usar un muelle de datos Specifications en este ejemplo para consultar la base de datos. contractRepository es por lo tanto de tipo JpaSpecificationExecutor)

Cuestiones relacionadas