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 {
Imovel imovel = ImovelDAO.load(25); //minha entidade Imovel
ImobiliariaCriteria criteria = new ImobiliariaCriteria(); //minha entidade de atendimento
criteria.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 preciso
retorno += String.valueOf(criteria.list().size());
} catch (Exception ex) {
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.
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.
SELECT COUNT(I.*) FROM tab_imobiliaria I
WHERE
I.imovel = 25
AND
I.dataEntrada BETWEEN '2011-03-21 00:00:00' AND '2011-04-20 23:59:59';
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?
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)
[code]try {
Imovel imovel = ImovelDAO.load(25); //minha entidade Imovel
ImobiliariaCriteria criteria = new ImobiliariaCriteria(); //minha entidade de atendimento
criteria.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 preciso
retorno += String.valueOf(criteria.list().get(0));
} catch (Exception ex) {
ex.printStackTrace();
} [/code]
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.
eu fiz assim:
Imovel imovel = ImovelDAO.load(25);
ImobiliariaCriteria criteria = new ImobiliariaCriteria();
criteria.add(Restrictions.eq("imovel",imovel));
criteria.setProjection(Projections.rowCount());
retorno += String.valueOf(criteria.uniqueResult()) + " / ";
criteria.add(Restrictions.between("dataEntrada", dtInicio, dtFinal));
retorno += String.valueOf(criteria.uniqueResult());
mas queria saber se tem algum jeito de retornar tipo “20/3” direto…tem algum jeito naum?
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