Paginação JDBC

Boa tarde, estou desenvolvendo uma aplicação, com JSP, Spring, JDBC.
Tem uma tela de listagem que contem uma grande quantidade de dados, na hora de buscar no DB e listar na JSP está demorando um pouco devido a grande quantidade de dados. Então gostaria de saber como fazer a paginação.

Já li algumas soluções a respeito, usando SQL LIMIT e OFFSET mas não sei como implementar…

Método da controller onde eu pego todas as localidades e dispacho para a JSP

@RequestMapping ("/listarLocalidades")
	public String listarLocalidades(Model model){
		System.out.println("Localidades Controller: Listagem de localidades");
		model.addAttribute("localidades", dao.getAll());
		return "/listagem/listar_localidades";
	}

Método da DAO.

@Override
	public List<Localidade> getAll() {
		try {
			List<Localidade> localidades = new ArrayList<>();
			PreparedStatement stmt = this.connection.prepareStatement(
					"select * from tb_localidade_geo_idioma i INNER JOIN tb_localidade_georeferenciada l ON l.id_localidade_georeferenciada=i.id_localidade_georeferenciada");
			ResultSet rs = stmt.executeQuery();
			while (rs.next()) {
				localidades.add(populateLocalidades(rs));
			}
			return localidades;
		} catch (SQLException e) {
			throw new RuntimeException(e);
		}
	}

O seu método listarLocalidades(), sempre vai retornar um texto com o valor “/listagem/listar_localidades”. Esse método, é o mesmo que você fazer isso:

Se você for colocar sua lista em um atributo, para depois chama-lo no seu JSP, então você deve usar os protocolos HTTP. No caso, seria com um Servlet. Mais ou menos assim:

public void doGet(HttpServletRequest request, HttpServletResponse response)
	throws ServletException, IOException {
	listarLocalidades(request, response);
}
protected void listarLocalidades(HttpServletRequest request, HttpServletResponse response)
	throws ServletException, IOException {
	response.setContentType("text/html");
	response.setCharacterEncoding("utf-8");
	LocalidadeDao localidadeDao=new LocalidadeDao();
	// Depois de instanciar o seu Dao... Veja onde estou colocando a sua lista
	request.setAttribute("localidades", localidadeDao.getAll());
	// Note também como é redirecionado para a pagina do JSP
	request.getRequestDispatcher("index.jsp").forward(request, response);
}

Você disse também que demora um pouco por causa do tamanho da tabela que tem que buscar. Não estou acostumado com bancos relacionais mais, mas parece que seu modelo de dados pode ter muitos joins. Suponho que quase todas as suas tabelas tenham relacionamentos dos tipos, onetoone, manytomany, onetomany ou manytoone. Não sei, mas se for o caso, com certeza vai comprometer(E MUITO) a performance do seu banco. Rever ai na modelagem dos seus dados, se tem mesmo necessidade desses relacionamentos. Caso tenha, existe uma prática de projeto, onde você cria seus relacionamentos “NA APLICAÇÃO”. E no banco mesmo, não tem nem se quer “UM” relacionamento.

Bom dia Rodrigos_Bragas,

Cara a questão de pegar os dados e despachar para a JSP, está tranquila pois estou usando SPRING, e se quisesse também poderia usar o objeto request. Meu problema é com a questão da paginação, pois estou mandando os dados todos de uma vez para uma table, e devido ao grande volume demora um pouco para carregar a página.

Gostaria de por exemplo, conforme ele fosse mudando a página da tabela, fosse carregando de 10 em 10, 20 em 20 etc…

Não tem como eu mudar a modelagem do banco, pois se trata de uma aplicação mobile que já está em produção, e estou desenvolvendo o back-end da mesma.

Em breve eu terei que fazer uma pagina, onde seus itens carregam de 10 em 10, clicando no top 1, 2, 3, 4, etc… Bem parecido com o seu problema. Ainda não fiz, mas no meu projeto, esses itens chegam através de uma lista no formato JSON. Trato a lista com javascript e escrevo o HTML com os valores dos itens, como se cada item fosse um objeto. Cada objeto com suas Strings, Arrays, números, listas de links para imagens, e muitos outros dados.
O que poderíamos fazer?
-Poderíamos pegar o tamanho dessa lista, vamos supor que ela tem 45 itens. Dividir o tamanha por 10 (ou 20 se for de 20 em 20), e pegar apenas o numero inteiro, no caso 4. Com javascript, eu crio uma saida através de um loop até 4, onde vai criar uma variável HTML com o seguinte conteudo:

<ul class="topicoPaginacao" ><li value="1" >1</li><li value="2" >2</li>
<li value="3" >3</li><li value="4" >4</li></ul>

Com isso podemos criar uma função javascript, onde pega o valor de cada li, multiplica por 10, pegamos novamente a lista JSON, e extraímos apenas 10 tópicos por vez.
Por exemplo, vamos pensar em no menor e no maior array. Você primeiro multiplica o valor da li (clicada pelo usuário) por 10, para achar o valor maior. Como os itens serão mostrados apenas 10 por vez, o valor menor é o valor maior menos 10. A partir daqui é só escrever uma função javascript, que depois de receber o evento do click no tópico, ela pega sua lista JSON(que você trouce do seu servidor), extrai 10 itens da lista por vez, já gerando parte do seu HTML, para no fim gerar apenas um único texto com todo o conteúdo do HTML, que você vai imprimir em um determinado local da sua pagina HTML. Mais ou menos assim:

var maior=li.value*10;
var menor=maior-10;
var topicoHTML="";
for(int i=menor;i++;i<=maior) {
 //Agora é só usar o i para pegar o numero do array
 var iten="<div class=\"nome\">"+lista[i].get("nome")+"</div>"; 
 iten+="<div class=\"preco\">"+lista[i].get("preco")+"</div>"; 
topicoHTML+="<div class=\"produto\" >"+iten+"</div>";
}
//Local onde o conteúdo será trocado, ou incrementado dependendo do tipo de navegação.
var imprimir=document.getElementById("produtos");
imprimir.innerHTML=topicoHTML;

Esse meu exemplo é uma lógica para TROCAR o conteúdo, de acordo um os tópicos que ele clica. Se for para incrementar, muda o fato de que o menor valor da lista, vai ser sempre o primeiro do seu array, no caso a posição 0.
Você pode usar a mesma lógica com a lista diretamente que o banco de dados enviou para o servidor. Apenas, passando o valor da li para seu servidor. Lá ele vai tratar e te retornar um array.

Agora uma observação. Pelo que você esta fazendo, digo, passando diretamente um array Java, para sua pagina JSP. Tenho certeza que você não esta usando Ajax, logo sua pagina terá que ser totalmente carregada.
Digo isso, porque Ajax é usado pelo javascript, e até onde eu sei, você só envia array de java para javascript, se for em um formato JSON ou XML. Se for diretamente o seu ArrayList(), então você “consegue passar” por atributo. Na verdade você nem passa não. O que acontece, é que sua pagina HTML vai ser totalmente gerada no servidor, seja através de JSP/Servlet ou Spring, para depois então ser enviada e caregada no Navegador de quem tiver acessando seu site.
Quer ver a importância do ajax e uma aplicação com boas praticas de uso?
Entre em algum canal do youtube(Porta dos Fundos que muita gente conhece e tem muitos videos), e vai na parte de videos. Crica em carregar mais. Note que foi bem rápido e a pagina não precisou ser recarregada. O servidor do youtube é rápido também, mas, e de um site que não é? Imagina ter que carregar a página toda de novo.
Bom, é isso e espero ter ajudado. Do resto, vai mais uma questão de lógica de programação mesmo e como você trabalha com dados.