2012-05-06 10 views
12

Ich erstelle ein Hibernate-Kriterium, das prüft, ob ein Vertrag während eines Jahres gültig ist/war. Der Vertrag hat ein Start- und Enddatum als Standarddatumsfeld.Hibernate Kriterien Extrahieren Year from date

So zu SQL-Server verwendet wird, würde ich etwas in den Zeilen dieses SQL denken:

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

Die Question das Jahr als ganze Zahl angegeben ist.

Also, wie dies zu einem Winterschlaf Kriterium zu transformieren?

Wie Sie sehen können, fehlt mir das Bit, wo ich das Datum in ein Jahr umwandelt, damit es verglichen werden kann. Natürlich läuft mein Code nicht so wie er ist.

Irgendwelche Vorschläge, wie Sie die gewünschten Ergebnisse erhalten?

Antwort

13

Es scheint wie die API nicht direkt unterstützt, was Sie wollten, aber es gibt Abhilfe, die Sie sich anschauen sollten lösen.

Lösung 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(); 
} 

Beispiel Ausgang der beiden Methoden:

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 

Lösung 2:

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

Lösung 1 ist eine schöne saubere Alternative, wenn die 'toEndOfYear' Methode 1 addieren, sollte Jahr als es in 'cal.set' ging, sonst erhalten Sie das Ende des Vorjahres – Numeron

5

Verwenden Restrictions.sqlRestriction, die Ihr Problem

3

Wenn Sie JPA criteriaBuilder verwenden, können Sie Verwenden Sie die criteriaBuilder.function Methode. Z.B.

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); 
    } 
}); 

(verwende ich Spring Data Specifications in diesem Beispiel die Datenbank abzufragen. contractRepository ist also vom Typ JpaSpecificationExecutor)