Commit 7ec39503013e8dc400c0abe8bddd80e9eb455292

Authored by Emerson Oliveira
1 parent ddf1a667
Exists in master

Inclusão do capítulo de Paginação no Guia de Referencia do Demoiselle.

documentation/reference/pt-BR/master.xml
... ... @@ -41,7 +41,7 @@
41 41 <xi:include href="logger.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
42 42 <xi:include href="templates.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
43 43 <xi:include href="security.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
44   - <!-- <xi:include href="paginacao.xml" xmlns:xi="http://www.w3.org/2001/XInclude" /> -->
  44 + <xi:include href="paginacao.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
45 45 <xi:include href="properties.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
46 46 </part>
47 47 <!-- parte 2 -->
... ...
documentation/reference/pt-BR/paginacao.xml
... ... @@ -3,179 +3,288 @@
3 3 "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" []>
4 4 <chapter id="paginacao">
5 5  
6   - <title>Paginação</title>
  6 + <title>Paginação</title>
7 7  
8   - <para>
9   - Neste capítulo serão considerados os seguintes assuntos:
10   - <itemizedlist>
11   - <listitem>motivação para o uso de um mecanismo padronizado para <emphasis>paginação</emphasis>;</listitem>
12   - <listitem>funcionamento e uso da estrutura <literal>Pagination</literal> e do contexto de paginação (<literal>PaginationContext</literal>).</listitem>
13   - </itemizedlist>
14   - </para>
15   -
16   - <section>
17   - <title>Introdução ao mecanismo</title>
18   - <para>
19   - A apresentação de conjuntos de registros de médio a grande porte em formato de tabelas em aplicações Web geralmente requer um
20   - <emphasis>mecanismo de paginação</emphasis>, o qual permite ao cliente ver apenas um pedaço do resultado final, podendo este
21   - navegar para frente e para trás através dos registros. A menos que o conjunto de registros seja garantidamente pequeno, qualquer
22   - aplicação do tipo Web com funcionalidades de busca precisa ser dotada de paginação.
23   - </para>
24   - <para>
25   - O mecanismo de paginação para as aplicações fornecido pelo <emphasis>Demoiselle Framework</emphasis> consiste em um algoritmo de
26   - direcionado ao banco de dados (i.e., Database-Driven Pagination). Essa abordagem, apesar de requerer instruções SQL específicas
27   - para obter porções determinadas de registros, é a mais utilizada por ser mais eficiente e produzir menos redundância dos dados.
28   - </para>
29   - <para>
30   - É fornecido em tempo de execução um <emphasis>contexto de paginação</emphasis>, o qual tem escopo de sessão e armazena a informação
31   - de paginação de cada entidade (i.e., bean) que necessite de tal mecanismo. Esse contexto é compartilhado entre as diversas camadas
32   - da aplicação, especificamente entre as camadas de visão e persistência. Dessa maneira, a paginação dos dados é transparente para a
33   - camada intermediária (i.e., negócio) e não interfere na modelagem das classes de um projeto.
34   - </para>
35   - </section>
36   -
37   - <section>
38   - <title>Códigos de suporte</title>
39   - <!--
40   - <para>
41   - // TODO: explicar Pagination e PaginationContext
42   - </para>
43   - -->
44   - <para>
45   - Veremos na seção seguinte como implementar a paginação em uma aplicação Java.
46   -
47   - - Farão parte do código de suporte para paginação:
48   - * a classe Pagination: usada para manipular a paginação dos dados resultantes, contendo os campos currentPage (página atual, selecionada na camada de visão), pageSize (tamanho da página, a quantidade de registros que ela comportará) e totalResults (a quantidade de resultados existentes na base de dados);
49   - * a classe PaginationContext: contexto usado para armazenar e fornecer estruturas do tipo Pagination;
50   - * a classe PaginationConfig: armazenador de configurações referentes à paginação.
51   -
52   -- Códigos internos de suporte no Core:
53   -
54   - <programlisting role="JAVA"><![CDATA[
55   -
56   -public class Pagination {
57   -
58   - private int currentPage;
59   - private int pageSize;
60   -
61   - private Long totalResults;
62   - private Integer totalPages;
63   -
64   - // ...
65   -}
66   -
67   -@SessionScoped
68   -public class PaginationContext {
69   -
70   - private final Map<Class<?>, Pagination> map;
71   -
72   - public Pagination getPagination(Class<?> clazz) { ... }
73   -
74   - public Pagination get -->Pagination(Class<?> clazz, boolean create) { ... }
75   -
76   -}
77   -
78   -@Configuration
79   -public class PaginationConfig {
80   -
81   - @Key("default_page_size")
82   - private int defaultPageSize = 10;
83   -
84   - @Key("max_page_links")
85   - private int maxPageLinks = 5;
86   -
87   -}
88   -
89   - - Códigos internos de suporte em JPA:
90   -
91   -public class JPACrud<T, I> implements Crud<T, I> {
92   -
93   - @Inject
94   - private PaginationContext paginationContext;
95   -
96   - // ...
97   -
98   - public List<T> findAll() {
99   -
100   - final String jpql = "select this from " + getBeanClass().getSimpleName() + " this";
101   - final Query query = getEntityManager().createQuery(jpql);
102   -
103   - final Pagination pagination = paginationContext.getPagination(getBeanClass());
104   - if (pagination != null) {
105   - if (pagination.getTotalPages() == null) {
106   - pagination.setTotalResults(this.countAll());
107   - }
108   - query.setFirstResult(pagination.getFirstResult());
109   - query.setMaxResults(pagination.getPageSize());
110   - }
111   -
112   - // ...
113   - }
114   -
115   -}
116   -
117   - - Códigos internos de suporte em JSF:
118   -
119   -public abstract class AbstractListPageBean<T, I> extends AbstractPage implements ListPageBean<T, I> {
120   -
121   - @Inject
122   - private PaginationContext paginationContext;
123   -
124   - @Inject
125   - private PaginationConfig paginationConfig;
126   -
127   - // ...
128   -
129   - public Pagination getPagination() {
130   - return paginationContext.getPagination(getBeanClass(), true);
131   - }
132   -
133   - public int getPageSize() {
134   - return paginationConfig.getDefaultPageSize();
135   - }
136   -
137   - public int getMaxPageLinks() {
138   - return paginationConfig.getMaxPageLinks();
139   - }
140   -
141   -}
142   -
143   -frameworkdemoiselle.pagination.default_page_size=50
144   -frameworkdemoiselle.pagination.max_page_links=10
145   -
146   -]]></programlisting>
147   - </para>
148   - </section>
  8 + <para>
  9 + Neste capítulo serão considerados os seguintes assuntos:
  10 + <itemizedlist>
  11 + <listitem><para>Motivação para o uso de um mecanismo padronizado para <emphasis>paginação</emphasis>;</para></listitem>
  12 + <listitem><para>Funcionamento e uso da estrutura <literal>Pagination</literal> e do contexto de paginação
  13 + (<literal>PaginationContext</literal>).</para></listitem>
  14 + </itemizedlist>
  15 + </para>
  16 +
  17 + <section>
  18 + <title>Introdução ao mecanismo</title>
  19 + <para>
  20 + A apresentação de conjuntos de registros de médio a grande porte em formato de tabelas em aplicações Web geralmente requer um
  21 + <emphasis>mecanismo de paginação</emphasis>, o qual permite ao cliente ver apenas um pedaço do resultado final, podendo este
  22 + navegar para frente e para trás através dos registros. A menos que o conjunto de registros seja garantidamente pequeno, qualquer
  23 + aplicação do tipo Web com funcionalidades de busca precisa ser dotada de paginação.
  24 + </para>
  25 + <para>
  26 + O mecanismo de paginação para as aplicações fornecido pelo <emphasis>Demoiselle Framework</emphasis> consiste em um algoritmo
  27 + direcionado ao banco de dados (i.e., Database-Driven Pagination). Essa abordagem, apesar de requerer instruções SQL específicas
  28 + para obter porções determinadas de registros, é a mais utilizada por ser mais eficiente e produzir menos redundância de dados,
  29 + diminuindo assim tráfego de rede, consumo de memória e reduzindo o tempo de resposta.
  30 + </para>
  31 + <para>
  32 + É fornecido em tempo de execução um <emphasis>contexto de paginação</emphasis>, o qual tem escopo de sessão e armazena a informação
  33 + de paginação de cada entidade (i.e., bean) que necessite de tal mecanismo. Esse contexto é compartilhado entre as diversas camadas
  34 + da aplicação, especificamente entre as camadas de visão e persistência. Dessa maneira, a paginação dos dados é transparente para a
  35 + camada intermediária (i.e., negócio) e não interfere na modelagem das classes de um projeto.
  36 + </para>
  37 + </section>
  38 +
  39 + <section>
  40 + <title>Códigos de suporte</title>
  41 + <!--
  42 + <para>
  43 + // TODO: explicar Pagination e PaginationContext
  44 + </para>
  45 + -->
  46 + <para>
  47 + O <emphasis>mecanismo de paginação</emphasis> do <emphasis>Demoiselle Framework</emphasis> permite que os parâmetros para a consulta
  48 + no banco sejam configurados de forma bastante prática. Por outro lado, a consulta paginada ao banco já é feita pela extensão
  49 + <literal>demoiselle-jpa</literal>. Dessa forma, basta ajustar os parametros da paginação, e pedir as consultas normalmente.
  50 + O resultado da consulta é então passado para algum componente de iteração de dados com suporte ao mecanismo conhecido como <emphasis>Lazy
  51 + Load</emphasis> (ou <emphasis>Lazy Loading</emphasis>).
  52 + </para>
  53 + <para>
  54 + Farão parte do código de suporte para paginação:
  55 + <itemizedlist>
  56 + <listitem>
  57 + <para>
  58 + A classe <literal>Pagination</literal>: usada para manipular a paginação dos dados resultantes, contendo os campos <literal>currentPage</literal>
  59 + (página atual, selecionada na camada de visão), <literal>pageSize</literal> (tamanho da página, a quantidade de registros que ela comportará)
  60 + e <literal>totalResults</literal> (a quantidade de resultados existentes na base de dados);
  61 + </para>
  62 + </listitem>
  63 + <listitem>
  64 + <para>
  65 + A classe <literal>PaginationContext</literal>: contexto usado para armazenar e fornecer estruturas do tipo <literal>Pagination</literal>;
  66 + </para>
  67 + </listitem>
  68 + <listitem>
  69 + <para>
  70 + A classe <literal>PaginationConfig</literal>: armazenador de configurações referentes à paginação.
  71 + </para>
  72 + </listitem>
  73 + </itemizedlist>
  74 + </para>
  75 +
  76 + <para>Códigos internos de suporte no Core:</para>
  77 +
  78 + <programlisting role="JAVA"><![CDATA[
  79 + public class Pagination {
  80 +
  81 + private int currentPage;
  82 + private int pageSize;
  83 +
  84 + private Long totalResults;
  85 + private Integer totalPages;
  86 +
  87 + // ...
  88 + }
  89 +
  90 + @SessionScoped
  91 + public class PaginationContext {
  92 +
  93 + private final Map<Class<?>, Pagination> map;
  94 +
  95 + public Pagination getPagination(Class<?> clazz) { ... }
  96 +
  97 + public Pagination get -->Pagination(Class<?> clazz, boolean create) { ... }
  98 +
  99 + }
  100 +
  101 + @Configuration
  102 + public class PaginationConfig {
  103 +
  104 + @Key("default_page_size")
  105 + private int defaultPageSize = 10;
  106 +
  107 + @Key("max_page_links")
  108 + private int maxPageLinks = 5;
  109 +
  110 + }
  111 + ]]></programlisting>
  112 +
  113 + <para>Códigos internos de suporte em JPA:</para>
  114 +
  115 + <programlisting role="JAVA"><![CDATA[
  116 + public class JPACrud<T, I> implements Crud<T, I> {
  117 +
  118 + @Inject
  119 + private PaginationContext paginationContext;
  120 +
  121 + // ...
  122 +
  123 + public List<T> findAll() {
  124 +
  125 + final String jpql = "select this from " + getBeanClass().getSimpleName() + " this";
  126 + final Query query = getEntityManager().createQuery(jpql);
  127 +
  128 + final Pagination pagination = paginationContext.getPagination(getBeanClass());
  129 + if (pagination != null) {
  130 + if (pagination.getTotalPages() == null) {
  131 + pagination.setTotalResults(this.countAll());
  132 + }
  133 + query.setFirstResult(pagination.getFirstResult());
  134 + query.setMaxResults(pagination.getPageSize());
  135 + }
  136 +
  137 + // ...
  138 + }
  139 +
  140 + }
  141 + ]]></programlisting>
  142 +
  143 + <para>Códigos internos de suporte em JSF:</para>
  144 +
  145 + <programlisting role="JAVA"><![CDATA[
  146 + public abstract class AbstractListPageBean<T, I> extends AbstractPage
  147 + implements ListPageBean<T, I> {
  148 +
  149 + @Inject
  150 + private PaginationContext paginationContext;
  151 +
  152 + @Inject
  153 + private PaginationConfig paginationConfig;
  154 +
  155 + // ...
  156 +
  157 + public Pagination getPagination() {
  158 + return paginationContext.getPagination(getBeanClass(), true);
  159 + }
  160 +
  161 + public int getPageSize() {
  162 + return paginationConfig.getDefaultPageSize();
  163 + }
  164 +
  165 + public int getMaxPageLinks() {
  166 + return paginationConfig.getMaxPageLinks();
  167 + }
  168 +
  169 + }
  170 + ]]></programlisting>
  171 + </section>
149 172  
150   - <section>
151   - <title>Implementação na aplicação</title>
152   - <para>
153   - Eis um exemplo de implementação de paginação em uma aplicação:
154   - </para>
155   - <programlisting role="JAVA"><![CDATA[
156   - @Inject
157   - private PaginationContext paginationContext;
158   -]]></programlisting>
159   - <programlisting role="JAVA"><![CDATA[
160   - Pagination pagination = paginationContext.getPagination(Audit.class);
161   -]]></programlisting>
162   - <tip>
163   - <para>
164   - O método <literal>getPagination()</literal> do contexto <literal>PaginationContext</literal> é sobrecarregado, podendo aceitar
165   - os seguintes argumentos: <literal>Class</literal> ou <literal>Class</literal> e <literal>boolean</literal>.
166   - </para>
167   - </tip>
168   - <note>
169   - <para>
170   - A JPA 2.0, através da Query API, suporta controle de paginação independente de fornecedor de banco de dados.
171   - Para controlar a paginação, a interface <literal>Query</literal> define os métodos <literal>setFirstResult()</literal> e
172   - <literal>setMaxResults()</literal> para especificar o primeiro resultado a ser recebido e o número máximo de resultados a
173   - serem retornados em relação àquele ponto. Internamente, são usadas instruções específicas do SGBD (ex: LIMIT e OFFSET no
174   - PostgreSQL).
175   - </para>
176   - </note>
  173 + <section>
  174 + <title>Implementação na aplicação</title>
  175 + <para>
  176 + Veremos nessa seção como implementar a paginação em uma aplicação Java. Para esse exmplo tomamos como base a aplicação de Bookmarks
  177 + fornecida pelo arquétipo <emphasis>JSF com JPA</emphasis> do <emphasis>Demoiselle Framework</emphasis> (para maiores detalhes
  178 + ver <link linkend="estrutura">Arquétipos</link>). Iremos utilizar o componente <literal>DataTable</literal> do <emphasis>PrimeFaces</emphasis>,
  179 + que oferece o mecanismo de <emphasis>Lazy Loading</emphasis> conhecido como <literal>LazyDataModel</literal>, muito útil para paginação
  180 + e classificação de dados.
  181 + </para>
  182 + <para>
  183 + Primeiro é preciso configurar um objeto <literal>LazyDataModel</literal> no construtor do <emphasis>Managed Bean</emphasis>
  184 + (<emphasis>BookmarkList</emphasis> nesse exemplo): instancia-lo e sobrescrever o método abstrado <literal>load</literal>, que recebe
  185 + vários argumentos. Esses argumentos são recuperados na página <literal>jsf</literal> que carrega a instância do objeto <literal>LazyDataModel</literal>.
  186 + </para>
  187 + <para>
  188 + Dentro do método <literal>load</literal> iremos pegar do contexto de paginação uma instância da implementação da interface <literal>Pagination</literal>
  189 + e ajustar alguns dos seus parâmetros para: indicar a partir de qual item a paginação deve iniciar, e o tamanho (quantidade de itens) de cada página.
  190 + Esses dados são usados no método <literal>findAll()</literal>, da classe <literal>JPACrud</literal> (extensão JPA), que utiliza o contexto de
  191 + paginação para pegar os parametros e fazer a consulta no banco buscando apenas os itens que estão dentro da pagina que o parametro
  192 + <literal>first</literal> indicar. O resultado é passado para a instancia do <literal>LazyDataModel</literal>, que é responsável por exibir
  193 + os dados de forma apropriada.
  194 + </para>
  195 + <para>
  196 + À classe <emphasis>BookmarkList</emphasis> devem ser adicionados os seguintes trechos de código:
  197 + </para>
  198 +
  199 + <programlisting role="JAVA"><![CDATA[
  200 + // ...
  201 + import java.util.Map;
  202 + import br.gov.frameworkdemoiselle.pagination.Pagination;
  203 +
  204 + // ...
  205 + private LazyDataModel<Bookmark> lazyModel;
  206 +
  207 + public BookmarkListMB() {
  208 + lazyModel = new LazyDataModel<Bookmark>() {
  209 +
  210 + @Override
  211 + public List<Bookmark> load (int first, int pageSize, String sortField,
  212 + SortOrder sortOrder, Map<String, String> filters){
  213 +
  214 + Pagination pagination = getPagination();
  215 + pagination.setPageSize(pageSize);
  216 + pagination.setFirstResult(first);
  217 +
  218 + List<Bookmark> itemsList = bc.findAll();
  219 +
  220 + lazyModel.setRowCount(pagination.getTotalResults());
  221 +
  222 + return itemsList;
  223 + }
  224 + };
  225 + }
  226 +
  227 + // ...
  228 +
  229 + public LazyDataModel<Bookmark> getLazyModel() {
  230 + return lazyModel;
  231 + }
  232 +
  233 + // ...
  234 + ]]></programlisting>
  235 +
  236 + <para>
  237 + No arquivo <literal>messages.properties</literal> adicione as linhas:
  238 + </para>
  239 +
  240 + <programlisting role="JAVA"><![CDATA[
  241 + page.first=0
  242 + page.rows=4
  243 + page.max.links=3
  244 + ]]></programlisting>
  245 +
  246 + <para>
  247 + Na página JSF <literal>bookmark_list.xhtml</literal>, substitua a linha:
  248 + </para>
  249 +
  250 + <programlisting role="JAVA"><![CDATA[
  251 + <p:dataTable id="list" var="bean" value="#{bookmarkListMB.resultList}">
  252 + ]]></programlisting>
  253 +
  254 + <para>
  255 + por:
  256 + </para>
  257 +
  258 + <programlisting role="JAVA"><![CDATA[
  259 + <p:dataTable id="list" var="bean"
  260 + value="#{bookmarkListMB.lazyModel}" lazy="true" paginator="true"
  261 + first="#{messages['page.first']}" rows="#{messages['page.rows']}"
  262 + pageLinks="#{messages['page.max.links']}">
  263 + ]]></programlisting>
  264 +
  265 + <para>
  266 + Com essas alterações simples, a aplicação Bookmarks passa a utilizar o mecanismo de paginação oferecido pelo <emphasis>Demoiselle Framework</emphasis>.
  267 + </para>
  268 +
  269 + <tip>
  270 + <para>
  271 + O método <literal>getPagination()</literal> do contexto <literal>PaginationContext</literal> é sobrecarregado, podendo aceitar
  272 + os seguintes argumentos: <literal>Class</literal> ou <literal>Class</literal> e <literal>boolean</literal>.
  273 + </para>
  274 + </tip>
  275 + <note>
  276 + <para>
  277 + A JPA 2.0, através da Query API, suporta controle de paginação independente de fornecedor de banco de dados.
  278 + Para controlar a paginação, a interface <literal>Query</literal> define os métodos <literal>setFirstResult()</literal> e
  279 + <literal>setMaxResults()</literal> para especificar o primeiro resultado a ser recebido e o número máximo de resultados a
  280 + serem retornados em relação àquele ponto. Internamente, são usadas instruções específicas do SGBD (ex: LIMIT e OFFSET no
  281 + PostgreSQL).
  282 + </para>
  283 + </note>
177 284 </section>
178 285  
  286 +</chapter>
  287 +
179 288 <!--<section>
180 289 <title>Um exemplo usando PrimeFaces</title>
181 290 <para>
... ... @@ -238,7 +347,7 @@ public class AuditMB extends AbstractListPageBean&lt;Audit, Long&gt; {
238 347 rows="#{auditMB.pageSize}" pageLinks="#{auditMB.maxPageLinks}">]]></programlisting>
239 348 </section>
240 349 -->
241   -
  350 +<!--
242 351 <section>
243 352 <title>Referências</title>
244 353 <itemizedlist>
... ... @@ -246,8 +355,8 @@ public class AuditMB extends AbstractListPageBean&lt;Audit, Long&gt; {
246 355 <listitem>Implementing Search Result Pagination in a Web Application (http://www.developer.com/java/other/article.php/3696226/)</listitem>
247 356 <listitem>A Pagination Technique Using Spring (http://www.developer.com/java/web/article.php/10935_3830886_1/)</listitem>
248 357 <listitem>Spring JDBC Pagination Tutorial (http://www.codefutures.com/tutorials/spring-pagination/)</listitem>
249   - <!-- <listitem>PrimeFaces DataTable - Lazy Loading (http://www.primefaces.org/showcase/ui/datatableLazy.jsf)</listitem> -->
  358 + <listitem>PrimeFaces DataTable - Lazy Loading (http://www.primefaces.org/showcase/ui/datatableLazy.jsf)</listitem>
250 359 </itemizedlist>
251 360 </section>
252   -
253   -</chapter>
  361 + -->
  362 +
... ...