Aide pour le lazy loading

Voici un article sur le sujet (attention, la signature de la méthode load de LazyDataModel a changé depuis l'écriture de l'article : depuis la version 8.0 de PrimeFaces, filters a maintenant le type Map<String,FilterMeta>, mais l'idée est toujours la même) et la démo de PrimeFaces qui donne les bases mais qui travaille avec des données dans un tableau et pas dans une base de données. Javadoc de LazyDataModel de la version 8.0 de PrimeFaces.

Page JSF

Pas beaucoup de changements ; dans <p:dataTable> :

Backing bean

Le gros travail est de définir la classe qui hérite de la classe LazyDataModel<CompteBancaire> (classe de Primefaces) et qui sera utilisée pour créer le modèle qui sera passé à la dataTable. La méthode à redéfinir est la méthode load.

Le plus clair serait d'écrire une classe à part qui hérite de LazyDataModel<CompteBancaire>.

Le modèle utilisé par la dataTable, instance de cette classe, est créé à la création du backing bean (méthode annotée avec @PostConstruct).

Exemple de page et backing bean

Page Web qui contient la table :

   <p:dataTable value="#{gestionComptes_lazy.model}" rows="4" lazy="true" ...>

Backing bean :

@Named(value = "gestionComptes_lazy")
@ViewScoped
public class GestionComptesBeanLazy implements Serializable {

    private LazyDataModel<CompteBancaire> model;

    @EJB
    private GestionnaireCompte gestionnaireCompte;

    public LazyDataModel<CompteBancaire> getModel() {
        return model;
    }

    @PostConstruct
    public void init() {
        System.out.println("CREATION LazyComptesDataModel");
        this.model = new LazyComptesDataModel(gestionnaireCompte);
    }
    
    ...
}

Classe qui implémente LazyDataModel :

/**
 * Modèle pour la table "lazy" qui affiche tous les comptes bancaires.
 */
public class LazyComptesDataModel extends LazyDataModel<CompteBancaire> {

    private final GestionnaireCompte gestionnaireCompte;

    public LazyComptesDataModel(GestionnaireCompte gestionnaireCompte) {
        this.gestionnaireCompte = gestionnaireCompte;
    }
    
    @Override
    public List<CompteBancaire> load(int first, int pageSize, String sortField, 
            SortOrder sortOrder, Map<String, FilterMeta> filters) {
        this.setRowCount(gestionnaireCompte.count(filters));
        List<CompteBancaire> comptes = 
                gestionnaireCompte.getPageTable(first, pageSize, sortField, sortOrder, filters);
        return comptes;
    }

EJB session sans état

Le backing bean s'appuie sur un EJB session sans état (vous pouvez choisir l'EJB qui a servi jusqu'à maintenant) qui contient une méthode (nommée getPageTable dans le code ci-dessus) qui retourne les informations depuis la base de données et le gros travail est donc d'écrire cette méthode. Elle retourne les lignes de la base qui doivent être affichées entre les positions m et n (n = m + taille page de la dataTable - 1) dans la table, sachant que la table peut être triée et qu'elle ne contient pas nécessairement toutes les données si l'utilisateur a filtré les données en utilisant des filtres de la dataTable PrimeFaces.

Les informations sur l'état de la table seront fournies par PrimeFaces au moment d'afficher une nouvelle page de la table (elles sont passées en paramètre à la méthode load ci-dessus) :

Une petite difficulté supplémentaire : avec PrimeFaces le développeur a le choix des types de filtres (avec l'attribut filterMatchMode) : startsWith (valeur par défaut), endsWith, contains, exact, lt (less than), lte, gt, gte, equals, in. La méthode doit donc tenir compte du type de filtre. Le développeur sait bien le type qu'il a choisi pour les colonnes ; n'essayez pas d'écrire une méthode générique qui marcherait pour tous les types de filtre.

Il n'est pas difficile d'écrire un modèle si on suppose que la table ne sera pas triée ni filtrée. Sinon il faut écrire la requête JPA en tenant compte d'un tri et d'un ou plusieurs filtres sur les colonnes. Vous pouvez écrire la version simple (sans filtre ni tri) et la tester.

Si vous avez le temps, ajoutez seulement ensuite le tri et les filtres en vous aidant d'exemples trouvés sur le Web. Vous aurez un exemple dans le projet NetBeans exporté sous la forme d'un fichier zip, donné à la fin du TP.