Implementando Criterion para utilizar Extract do Oracle

Ontem meu amigo Filipe Sabella queria executar uma função para manipulação de data do Oracle utilizando Criteria. Algo do tipo funcao_do_oracle( columa ) = ?

O Hibernate não implementa esse tipo de funcionalidade, mas por ter seu desenvolvimento baseado em interfaces lhe possibilita extender / criar (quase) toda e qualquer funcionalidade que deseje. Depois de dar o caminho das pedras, dizendo que era “so” implementar Criterion e algumas alterações para deixarmos a mesma compativel com 1.4 chegamos a seguinte solução:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
package br.com.dclick.hibernate.criterion.oracle;

import org.hibernate.Criteria;
import org.hibernate.EntityMode;
import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.criterion.CriteriaQuery;
import org.hibernate.criterion.Criterion;
import org.hibernate.engine.TypedValue;

public class ExtractFunctionExpression implements Criterion {

    private static final class ExtractType {

        private String function;

        private ExtractType( String function ) {
            this.function = function;
        }

        public String toString() {
            return function.toString();
        }

    }

    public static final ExtractType YEAR = new ExtractType( "YEAR" );
    public static final ExtractType MONTH = new ExtractType( "MONTH" );
    public static final ExtractType DAY = new ExtractType( "DAY" );

    private String property;
    private String value;
    private ExtractType extractType;

    public ExtractFunctionExpression( String property, ExtractType extractType, String value ) {
        this.property = property;
        this.extractType = extractType;
        this.value = value;
    }

    public TypedValue[] getTypedValues( Criteria criteria, CriteriaQuery criteriaQuery ) throws HibernateException  {
        return new TypedValue[] { new TypedValue( Hibernate.STRING, value, EntityMode.POJO ) };
    }

    public String toSqlString( Criteria criteria, CriteriaQuery criteriaQuery ) throws HibernateException {
        String column = criteriaQuery.getColumnsUsingProjection( criteria, property )[ 0 ];
        return "( extract(" + extractType.toString() + " from " + column + " ) = ? )";
    }

}

Pronto. Agora e so adicionar ao seu criterio:

1
2
3
4
HibernateSessionFactory.getSession()
.createCriteria(Venda.class)
.add( new ExtractFunctionExpression("dataVenda", ExtractFunctionExpression.YEAR, "2007") )
.list();

2 comentários

  1. Geissivan em 11.ago.09 às 9:55 am

    Opa cara,

    Estava procurando como fazer isso a um tempim já.. só que não havia pensando em fazer uma implementação das minhas necessidades, valeu a dica, abraço.

  2. Felipe em 16.out.09 às 10:08 am

    Eu tive a necessidade de utilizar uma busca com TRUNC + TO_DATE do Oracle, e essa implementação de criterion serviu certinho.

    TRUNC( campo ) = TRUNC( TO_DATE( ? , ‘dd/MM/yyyy’) )

    Valeu a dica.

    Abraços

Deixe Seu Comentário