Como trazer conjuntos de resultados usando Criteria...?

15 respostas
D

Tenho uma situação que realmente não sei como resolver… tem a ver com conjuntos.

Considerando os seguintes registros:descrição data_inicial data_final linha1 01/01/2001 01/05/2005 linha2 01/01/2002 01/05/2005 linha3 01/01/2004 01/05/2005E desejo todos os registros que estejam DENTRO do período de 01/01/2003 até 31/05/2003

deveriam retornar as linha1 e linha2

linha3 não deve retornar, pois não está DENTRO do intervalo solicitado

COMO fazer isso com Hibernate?

15 Respostas

romarcio

Pelo que entendi a sua pesquisa seria assim:
data_inicial: 01/01/2003
data_final: 31/05/2003

Então, basta testar se a sua data_inicial é menor igual a data_final. Se for, a pesquisa vai retornar todas as datas iniciais que estiverem nesse intervalo. A data_inicial que for maior que a data_final não será retornada.

A consulta poderia ser assim:

O Restrictions.le(), é o mesmo que a condição de <=

D

romarcio:
Pelo que entendi a sua pesquisa seria assim:
data_inicial: 01/01/2003
data_final: 31/05/2003

Então, basta testar se a sua data_inicial é menor igual a data_final. Se for, a pesquisa vai retornar todas as datas iniciais que estiverem nesse intervalo. A data_inicial que for maior que a data_final não será retornada.

A consulta poderia ser assim:

O Restrictions.le(), é o mesmo que a condição de <=

Não funciona, pois, pexemplo, se eu passar o período de 2015 até 2016 esses registros não podem retornar e, segundo sua regra, eles retornariam.

romarcio

Eu não entendi o que você quis dizer.
Eu coloquei o código diferente do que eu falei, o certo pelo que eu disse seria assim:

List&lt;SuaClasse&gt; list = getSession().createCriteria(SuaClasse.class).add(Restrictions.le(&quot;data_Inicial&quot;, dataFinal)).list(); Teria que testar a data inical <= data final

pmlm

Queres todos os registos que se encontrem totalmente dentro do intervalo ou que apanhem qualquer parte do intervalo.

No teu exemplo, um registo de 01/01/2002 a 31/03/2003 deve ser devolvido?

romarcio
List&lt;SuaClasse&gt; list = getSession().createCriteria(SuaClasse.class)
.add(Restrictions.le("data_Inicial", dataFinal))
.add(Restrictions.ge("data_Final", dataInicial))
.list();

ge() é o mesmo que >=

Assim teriamos:
Data inicial <= data final
and
Data final >= data inicial

D

romarcio:
Assim teriamos:
Data inicial <= data final
and
Data final >= data inicial

exato! fiz uns testes aqui e cheguei ao mesmo where seu… creio q isso resolve! obrigado!

pmlm

Se queres apenas os resultados que se encontram totalmente no intervalo, resolve.
Se queres todos os resultados que se encontrem também parcialmente no intervalo, não resolve.

D

pmlm:
Se queres apenas os resultados que se encontram totalmente no intervalo, resolve.
Se queres todos os resultados que se encontrem também parcialmente no intervalo, não resolve.

No meu caso preciso dos resultados que se encontrem também parcialmente. Como poderia resolver isso?

romarcio

Olha só, criei o seguinte caso de teste:

id 	dtInicio	dtFim
1	2001-01-01	2002-01-01
2	2001-01-01	2002-05-31
3	2001-01-01	2003-01-01
4	2002-01-01	2003-01-01
5	2002-01-01	2004-01-01 
6	2002-01-01 	2005-01-01 
7	2003-01-01	2003-05-31 *
8	2003-01-01	2005-01-01
9	2004-01-01	2004-05-31
10	2004-01-01	2005-01-01
11	2005-01-01	2005-05-31
12	2005-01-01	2006-01-01
13	2006-01-01 	2006-05-31

Para esse intervalo: 2003-01-01 a 2003-05-31
O único aceito seria o id=7

Então primeiro usamos a consulta com as seguintes restrições:
dtInicio <= dtFim And dtFim >= dtInicio

.add(Restrictions.le(&quot;dtInicio&quot;, fim)) .add(Restrictions.ge(&quot;dtFim&quot;, inicio))
E teremos todos esses resultados:

id=3, dtInicio=2001-01-01, dtFim=2003-01-01 id=4, dtInicio=2002-01-01, dtFim=2003-01-01 id=5, dtInicio=2002-01-01, dtFim=2004-01-01 id=6, dtInicio=2002-01-01, dtFim=2005-01-01 id=7, dtInicio=2003-01-01, dtFim=2003-05-31 * id=8, dtInicio=2003-01-01, dtFim=2005-01-01

Então uso mais uma restrição:
dtFim <= dtFim -> Assim elimina todas as datas que tinham a dtFim maior que o parâmetro dtFim

E o resultado passa a ser:

id=3, dtInicio=2001-01-01, dtFim=2003-01-01 id=4, dtInicio=2002-01-01, dtFim=2003-01-01 id=7, dtInicio=2003-01-01, dtFim=2003-05-31 *

Para finalizar, a ultima restrição:
dtInicio >= dtIncio -> Assim eliminamos todas as datas que estariam em um intervalo com dtInicio menor que o parâmetro de dtInicio

E o resultado final:

A consulta então seria essa:

List&lt;SuaClasse&gt; list = getSession().createCriteria(SuaClasse.class) .add(Restrictions.le("data_Inicial", dataFinal)) .add(Restrictions.ge("data_Final", dataInicial)) .add(Restrictions.le("data_Final", dataFinal)) .add(Restrictions.ge("data_Inicial", dataInicial)) .list();

OBS: Cria um caso de teste maior e com intervalos de datas mais bem distribuídos e faz um teste.

pmlm

Precisas de ver os registos de três situações:

  • Os que começam antes da data de inicio do intervalo e terminam depois dessa data de inicio
  • Os que começam antes da data de fim do intervalo e terminam depois dessa data de fim
  • Os que começam depois da data de inicio do intervalo e terminam antes da data de fim

Com estes três casos cobres todas as situações.

romarcio

pmlm:
Precisas de ver os registos de três situações:

  • Os que começam antes da data de inicio do intervalo e terminam depois dessa data de inicio
  • Os que começam antes da data de fim do intervalo e terminam depois dessa data de fim
  • Os que começam depois da data de inicio do intervalo e terminam antes da data de fim

Com estes três casos cobres todas as situações.

  • E os que começaram antes da data de inicio e terminaram na própria data de inicio, fazem parte do intervalo?
    Por exemplo, intervalo entre: 2003-01-01 a 2003-05-31. O intervalo: 2001-01-01 2003-01-01 é válido ou não?
pmlm

Qualquer antes ou depois das minhas regras devem ler-se como <= ou >=
:slight_smile:

romarcio

pmlm:
Qualquer antes ou depois das minhas regras devem ler-se como <= ou >=
:-)

Então essa consulta que eu tinha postado anteriormente está correta:

List<SuaClasse> list = getSession().createCriteria(SuaClasse.class)
.add(Restrictions.le("data_Inicial", dataFinal))
.add(Restrictions.ge("data_Final", dataInicial))
.list();

Ela abrange todas as regras, veja:

id 	dtInicio	dtFim
1	2001-01-01	2002-01-01 
2	2001-01-01	2002-05-31
3	2001-01-01	2003-01-01 A 
4	2002-01-01	2003-01-01 A 
5	2002-01-01	2004-01-01 A - B 
6	2002-01-01 	2005-01-01 A - B
7	2003-01-01	2003-05-31 D 
8	2003-01-01	2005-01-01 B 
9	2004-01-01	2004-05-31
10	2004-01-01	2005-01-01
11	2005-01-01	2005-05-31
12	2005-01-01	2006-01-01
13	2006-01-01 	2006-05-31	
14	2003-02-01	2003-03-01 C

Legenda:
A Os que começam antes da data de inicio do intervalo e terminam depois dessa data de inicio
B Os que começam antes da data de fim do intervalo e terminam depois dessa data de fim
C Os que começam depois da data de inicio do intervalo e terminam antes da data de fim
D O próprio intervalo

pmlm

Aparentemente sim… Isso funciona como um OR?

romarcio

Sim. Seria o mesmo que um select desse tipo:

select
       ID,
       DATA_FIM,
       DATA_INICIO
    from
        CADASTROS 
    where
        DATA_INICIO<= '2003-05-31'  and DATA_FIM>='2003-01-01'
Criado 10 de janeiro de 2012
Ultima resposta 11 de jan. de 2012
Respostas 15
Participantes 3