Pessoal estou com dificuldades para realizar uma consulta recebendo uma lista com os ids e retorno uma lista com os objetos hj estou fazendo assim:
public List<Funcionalidades> getListaFuncionalidadesById(List<Long> ids) {
List<Funcionalidades> toReturnListaFuncionalidades = new ArrayList<Funcionalidades>();
Funcionalidades funcionalidades;
Session session = getSession();
try {
for (Long id : ids) {
funcionalidades = (Funcionalidades) session.get(Funcionalidades.class, id);
if (funcionalidades != null) {
toReturnListaFuncionalidades.add(funcionalidades);
}
}
return toReturnListaFuncionalidades;
} catch (Exception ex) {
log.error("Erro ao recuperar as funcionalidades com a lista de isd informados. Erro: " + ex);
return null;
}
}
só que essa consulta esta demorando 300 ms estou achando muito lento pois na tebela do bando de dados tenho somente 54 registros, alguem pode me da uma luz de como otimizar essa consulta?
Bom, acho que você pode tentar usar load pode ser que seja mais rápido.
session.load(Funcionalidades.class, id);
ou você pode usar HQL com clausula WHERE, que é o mais rápido no hibernate.
acho que deve estar lento pelo seguinte:
se sua List<Long> ids contem 54 ids, vc está efetuando a consulta 54 vezes dentro de um laço “for”. Todos sabemos que um acesso a banco tem um certo custo e vc está multiplicando esse custo por 54!
em vez de buscar um por um dentro do laço, implemente uma consulta hql que utilize a clausula “where id in (:ids)” e passa a tua lista de ids como parâmetro da query.
assim, vc irá fazer apenas um acesso a banco.
Updt: seria mais ou menos isso:
public Collection<Funcionalidades> getListaFuncionalidadesById(Collection<Long> ids) throws Exception {
StringBuilder builder = new StringBuilder();
builder.append("select funcs from Funcionalidades funcs ").
append("where funcs.id in (:ids) ");
Query q = getSession().createQuery(builder.toString()); // import org.hibernate.Query;
q.setParameter("ids", ids);
return (Collection<Funcionalidades>) q.list();
}
[]s
Exatamente como disse antes, HQL é forma mais rápida.
Ok?
e se realmente quiser fazer com criteria é só fazer assim
public List getAll(){
Criteria c = session.createCriteria(classe);
return c.list();
}
Quando for necessario obter vários dados do banco tente ao máximo obter esses dados de uma só vez.
Obrigado pessoal fiz assim:
Criteria criteria = session.createCriteria(Funcionalidades.class);
criteria.add(Restrictions.in("idFuncionalidades", ids));
toReturnListaFuncionalidades = criteria.list();
tando usando esse codigo que fiz quanto usando o que o amigo sf.marcius postou, tem a mesma perfomace, porem usando o hql foi um milisegundo mais rapido
o que fiz demorou 17 milisegundos e o que o sf.marcius postou demorou 16 segundos. porem a lentidão não esta nessa consulta, achei que era, o mais incrivel é que usando esse código:
for (Long id : ids) {
funcionalidades = (Funcionalidades) session.get(Funcionalidades.class, id);
if (funcionalidades != null) {
toReturnListaFuncionalidades.add(funcionalidades);
}
}
a consulta demorou apenas 1 milisegundo, vc6 sabem porque? tenho um suspeita usando o codigo que fiz a query sql que o hibernate gereou ele faz um inner join e todos nos sabemos que os joins da vida são muito custosos para os sgbds a consulta usando o get ele não fez nenhum inner join, acho que pode ser isso, mais ainda não tenho certeza. Acho que meu problema esta aqui:
for (Grupos dadosGrupo : dadosGrupos) {
EventoDadosTelaGerenciamentoGrupos dadosTela = new EventoDadosTelaGerenciamentoGrupos(dadosGrupo.getNome(), dadosGrupo.getDescricao());
dadosTela.setTemUsuario(dadosGrupo.getUsuarios().isEmpty() ? false : true);
// Percorrendo as funcionalidades associadas ao grupo
for (Funcionalidades dadosFuncionalidade : dadosGrupo.getFuncionalidades()) {
dadosTela.getFuncionalidades().add(dadosFuncionalidade.getDescricao());
}
Collections.sort(dadosTela.getFuncionalidades());
dadosEventoAtualizarTela.add(dadosTela);
}
tenho que arrumar uma maneira de otimizar esse trecho de codigo.
pra ver qual foi o sql executado pelo hibernate, adiciona esses parametros no teu arquivo de config do hibernate.
hibernate.show_sql=true
hibernate.format_sql=true
e compara as consultas geradas que serao exibidas no log.
Obs: configura teu log para mostrar mensagens do Level.DEBUG pra cima.
PS: testa esse teu código com aquele Collections.Sort(…) comentado, só para ver se não dá um salto no desempenho.
acho que ele que deve estar comendo boa parte do tempo gasto no teu algoritmo.
Se for, vc terá que arrumar um meio mais eficaz de efetuar essa ordenação, se ela for realmente necessária. o ideal é que os dados ja viessem ordenados na consulta.
[]s
Cara isso me deu um pouco de trabalho pra achar mas como não gosto de deixar ninguem sem resposta e tava curioso pra saber como era encontrei nesse link aqui
http://www.vbmania.com.br/pages/index.php?varModulo=Forum&varMethod=abrir&varID=311357
tenta fazer assim e verifica o desempenho
public List<Funcionalidades> getListaFuncionalidadesById(List<Long> ids) {
List<Funcionalidades> toReturnListaFuncionalidades;
Session session = getSession();
Criteria criteria = session.createCriteria(Fincionalidades.class);
criteria.add(Restrictions.in("id", ids));
toReturnListaFuncionalidades = criteria.list();
return toReturnListaFuncionalidades;
}
como eu te disse é tudo uma questão de recuperar todos os registros necessários de uma só vez, fazer várias querys como estava sendo feito vai consumir muito processamento.