[RESOLVIDO]Ajuda em Busca Hibernate + Spring

Bom dia.

Preciso fazer uma busca que retorno os valores do BD. Isso eu consigo fazer sem problemas, depois de muito apanhar do hibernate agora consigo fazer buscas com ele sem problema, mas essa está me deixando confuso. A busca em questão é a seguinte:

Preciso retornar o último valor de Fornecedor que foi incluído no BD faço assim:

DetachedCriteria crit = DetachedCriteria.forClass(CadastroFornecedor.class) .setProjection(Projections.max("codigoCadastro")); return getHibernateTemplate().findByCriteria(crit);

Esse valor me retorna a última id do banco, id essa que é inserida automáticamente pelo postgres.

O sistema deverá mostrar o último cliente inserido no banco ao abrir a tela de visualização(isso está funcionando). O problema que nessa tela possui dois botões PRÓXIMO e ANTERIOR e esses botões deverão mostrar o Cliente que fez o cadastro antes e o que fez depois, ou seja será uma lista de clientes mostrando um por vez.

Qual seria a melhor opção. Retornar todos os clientes de uma vez que poderia “pesar” o sistema ou como eu havia pensado retornar um por vez, caso seja um por vez como deve ser feita busca do id anterior ou próximo. Eu poderia somar um ou diminuir um no valor da ID do último e fazer uma busca nesse novo valor, mas os cliente podem ser excluídos e isso pode gerar algum erro se eu apenas me orientar por id.

Alguem têm alguma dica?

Obrigado pelas possíveis respostas.

Olá Cledsonjr,

Primeiro, eu já fiz algo semelhante. Não sei se existe alguma peculiaridade quanto ao postgre, mas no meu caso, ao incluir uma Entity o atributo ID é populado automaticamente.
Enfim, no meu código eu simplesmente chamei o “.getId()” depois de chamar o método persist() e o código estava lá. No caso eu usei SQL Server com uma coluna IDENTITY.
Acredito que isso é muito melhor em questão de desempenho.

Além disso, não faça uma navegação por ID, como você mesmo observou vão haver muitas dores de cabeça.
O que dá pra fazer é “paginar” os resultados. Veja um exemplo:

String sql = "SELECT * FROM TableName"; Query query = em.createQuery(sql); query.setFirstResult(firstPosition); query.setMaxResults(numberOfRecords); List result = query.getResultList();

Se quiser mostrar 1 a 1, defina numberOfRecords como 1 e incremente ou decremente firstPosition cada vez que se clicar, respectivamente, em próximo e anterior.

[quote=utluiz]Olá Cledsonjr,

Primeiro, eu já fiz algo semelhante. Não sei se existe alguma peculiaridade quanto ao postgre, mas no meu caso, ao incluir uma Entity o atributo ID é populado automaticamente.
Enfim, no meu código eu simplesmente chamei o “.getId()” depois de chamar o método persist() e o código estava lá. No caso eu usei SQL Server com uma coluna IDENTITY.
Acredito que isso é muito melhor em questão de desempenho.

Além disso, não faça uma navegação por ID, como você mesmo observou vão haver muitas dores de cabeça.
O que dá pra fazer é “paginar” os resultados. Veja um exemplo:

String sql = "SELECT * FROM TableName"; Query query = em.createQuery(sql); query.setFirstResult(firstPosition); query.setMaxResults(numberOfRecords); List result = query.getResultList();

Se quiser mostrar 1 a 1, defina numberOfRecords como 1 e incremente ou decremente firstPosition cada vez que se clicar, respectivamente, em próximo e anterior.[/quote]

Muito Obrigado!

Era isso que estava procurando, porém como sou novato no Spring+Hibernate :oops: não estou conseguindo fazer a função.
Esse parâmetros query.setFirstResult(firstPosition); query.setMaxResults(numberOfRecords); deverei passar para o Dao?

Um Exemplo de uma função minha.

public List<CadastroFornecedor> listarFornecedorPeloCodigo(Integer codigoCadastro){ DetachedCriteria crit = DetachedCriteria.forClass(CadastroFornecedor.class) .add(Restrictions.eq("codigoCadastro", codigoCadastro)); return getHibernateTemplate().findByCriteria(crit); //return getHibernateTemplate().loadAll(CadastroFornecedor.class); }

Desculpe, o exemplo que mandei utiliza uma Query e não um DetachedCriteria.
Entretanto, pelo que vi aqui a classe DetachedCriteria é uma abstração da classe Criteria, mas não implementa os métodos setFirstResult ou setMaxResults.

Acho que você teria que alterar um pouco a implementação do método, sim. Primeiro recebendo por parâmetro a faixa de valores desejados. Depois mudando de DetachedCriteria para Criteria, pois esta disponibiliza od métodos necessários para limitar os resultados.

Links que podem ajudar:

Muito obrigado pela ajuda utluiz .

Vou dar uma olhada nos links. Mas carregar uma lista de cliente não pode ficar lento?

Acho que não fui muito claro. A ideia é fazer o mesmo de antes, mas usando a classe Criteria no lugar da DetachedCriteria.
Com a classe Criteria você vai ter acesso ao métodos setFirstResult e setMaxResults, para avançar e voltar nos registros.

Não ficaria mais lento porque você, na verdade, estará listando apenas 1 elemento por vez.
Você somente teria problemas de desempenho se o banco de dados não tiver bom suporte a paginação ou se seu critério de pesquisa não utilizar um índice, resultado num “table scan” (onde o banco precisa ler a tabela inteira). Esses problemas aparecem em qualquer sistema e é preciso fazer um ajuste fino quando a performance causa problemas.

[quote=utluiz]Acho que não fui muito claro. A ideia é fazer o mesmo de antes, mas usando a classe Criteria no lugar da DetachedCriteria.
Com a classe Criteria você vai ter acesso ao métodos setFirstResult e setMaxResults, para avançar e voltar nos registros.

Não ficaria mais lento porque você, na verdade, estará listando apenas 1 elemento por vez.
Você somente teria problemas de desempenho se o banco de dados não tiver bom suporte a paginação ou se seu critério de pesquisa não utilizar um índice, resultado num “table scan” (onde o banco precisa ler a tabela inteira). Esses problemas aparecem em qualquer sistema e é preciso fazer um ajuste fino quando a performance causa problemas.[/quote]

Você foi muito claro. Eu que sou lento.hehe

Estava com medo de ficar lento, pois estou com dataTable(primefaces) listando todos os clientes e essa função está me tirando o sono.hehe
E colocar mais uma função para deixar lento seria complicado, não sabia como o ResultSet funcionava. Enfim fiz a implementação e está funcionando corretamente com o botão próximo e anterior.

public List<CadastroFornecedor> listarTodosFornecedores(Integer codigo){ Criteria crit = getSession().createCriteria(CadastroFornecedor.class); crit.setFirstResult(codigo); crit.setMaxResults(1); return crit.list(); }

Muito obrigado novamente utluiz!!!.