Otimizar criteria - Como fazer uma criteria para trazer valores acumulados/Periodo?
5 respostas
leokaos
seguinte: tenho uma tabela de atendimentos e outra de imovel. cada atendimento tem data de entrada e uma referencia a imovel. Numa das telas do sistema eu preciso mostrar a quantidade de atendimentos que um determinado imovel teve. Entretando, o cliente precisa que seja da seguinte forma:
Atedimentos Acumulados / Atendimentos Do Período
Ou seja, preciso mostrar quantos atendimentos aquele imovel teve no total, e depois sobre um período de 30 dias: entaum fiz da seguinte forma:
try{Imovelimovel=ImovelDAO.load(25);//minha entidade ImovelImobiliariaCriteriacriteria=newImobiliariaCriteria();//minha entidade de atendimentocriteria.add(Restrictions.eq("imovel",imovel));retorno+=String.valueOf(criteria.list().size())+" / ";criteria.add(Restrictions.between("dataEntrada",dtInicio,dtFinal));//data inicial e final do periodo q precisoretorno+=String.valueOf(criteria.list().size());}catch(Exceptionex){ex.printStackTrace();}
entretando, o desempenho cai absurdamente qdo o volume de imoveis aumenta muito.
Alguem teria alguma forma mais performatica de fazer isso?
O que está pesando mesmo é o criteria.list().size() que obriga a carregar todos os registros.
Uma sugestão é usar Criteria + Projections para que retorne a contagem e não os registros.
Algo assim:
Provavelmente você terá que fazer duas, já que são duas contagens diferentes e você precisa fazer uma divisão.
Outra maneira que eu particularmente prefiro é usar uma Query específica que já traga o resultado usando createQuery.
leokaos
entendi…realmente naum tinha pensado na projections…
sobre a sugestão do query eu fiz assim inicialmente, mas achei melhor fazer por criteria… caso eu preciso trocar de banco naum preciso conferir se tem algum comando proprietario.
mas ainda assim eu preciso de 2 query, pra poder pegar os dois resultados neh? será q naum teria uma sql q conseguisse me dar os dois jah?
jamirdeajr
Agora que percebi que você quer os dois resultados separados para mostrar na tela.
Incluindo o Projections acho que funcionaria assim, em vez de pegar o list().size() você pega o list().get(0) - No rowCount ele retorna uma lista de resultados (só que só tem 1... talvez tenha outro meio de fazer isso, mas para mim foi como funcionou de primeira)
try{Imovelimovel=ImovelDAO.load(25);//minha entidade ImovelImobiliariaCriteriacriteria=newImobiliariaCriteria();//minha entidade de atendimentocriteria.add(Restrictions.eq("imovel",imovel));criteria.setProjection(Projections.rowCount());retorno+=String.valueOf(criteria.list().get(0))+" / ";criteria.add(Restrictions.between("dataEntrada",dtInicio,dtFinal));//data inicial e final do periodo q precisoretorno+=String.valueOf(criteria.list().get(0));}catch(Exceptionex){ex.printStackTrace();}
Ele vai fazer duas seleções, mas trará somente o count(*) nas duas vezes que deve ser bem rápido. Na segunda você apenas agrega a restrição de faixa de datas.
mas queria saber se tem algum jeito de retornar tipo “20/3” direto…tem algum jeito naum?
jamirdeajr
Usando SQL eu faria mais ou menos assim:
select count(I.*) , sum(case when I.dataEntrada BETWEEN '2011-03-21 00:00:00' AND '2011-04-20 23:59:59' then 1 else 0 end)
from tab_imobiliaria I
where
I.imovel = 25