Database
 sql >> Base de données >  >> RDS >> Database

Filtrage des données avec le RowSet JDBC

Parfois, les requêtes d'application à une base de données renvoient un grand nombre de lignes. Bien que les données récupérées soient mises en cache dans le ResultSet objet, il est souvent trop volumineux pour travailler avec eux. Par conséquent, nous devons pouvoir les filtrer dans différents ensembles de données pour limiter les lignes visibles. Cet article se penche sur la description de l'aspect filtrage de JDBC RowSet avec des exemples appropriés.

Un aperçu de RowSet

Ensemble de lignes est une interface qui complète l'API JDBC pour le modèle de composant JavaBeans. Il fournit un ensemble de propriétés qui permet à son instance d'être configurée pour se connecter à une source de données JDBC. Un RowSet instance est principalement utilisée pour récupérer des données à partir de la source de données. Les méthodes setter de cette interface sont utilisées pour renseigner les paramètres de la propriété command d'une requête SQL, qui est ensuite utilisée pour extraire des enregistrements de la base de données relationnelle. Parce que RowSet adhère au modèle de composant JavaBean, il prend en charge les événements JavaBean. Ces événements sont utilisés pour informer d'autres composants des événements, tels qu'un changement de valeur sur un ensemble de lignes. Parce que le RowSet L'interface est conçue comme une couche au-dessus du pilote JDBC, elle est ouverte à une implémentation personnalisée. Cette liberté permet au fournisseur de fabriquer sa propre réalisation affinée et de l'expédier avec le produit JDBC.

Le FilteredRowSet

Le FilteredRowSet est une extension d'interface du RowSet famille. Il existe une implémentation de référence de cette interface, appelée FilteredRowSetImpl classe. Pour fournir une implémentation personnalisée du FilteredRowSet interface, on peut soit étendre le FilteredRowSetImpl classe ou utilisez le FilteredRowSet interface selon vos besoins. À certaines occasions, nous devons appliquer une forme de filtrage sur le contenu que RowSet extractions. Une solution possible simple est de fournir un langage de requête pour tous les RowSet implémentations. Mais alors, ce n'est pas une approche viable car RowSet est construit avec l'idée d'un composant léger déconnecté. Cela alourdirait l'objet et irait à l'encontre de son principe de conception. Nous avons besoin d'une approche qui réponde au besoin mais qui n'injecte pas de langage de requête lourd avec la logique de traitement du filtrage. Le JDBC FilteredRowSet l'implémentation standard étend RowSet via les sous-interfaces telles que CachedRowSet et WebRowSet respectivement. Le FilteredRowSet peut manipuler le curseur à travers l'ensemble des méthodes de manipulation de curseur protégées fournies par le CachedRowSet interface. Ces méthodes peuvent être remplacées selon les besoins et aider lors du filtrage de RowSet contenu.

Un exemple rapide

Voici un exemple pour illustrer comment FilteredRowSet est utilisé pour stocker le contenu renvoyé par la requête envoyée à la base de données. Le résultat de la requête est filtré selon la configuration appliquée au FilteredRowset la mise en oeuvre. Cela définit le contenu visible ou les lignes qui nous intéressent à partir du résultat renvoyé par la requête. Dans l'exemple suivant, nous avons créé une classe de filtre appelée SimpleFilter . Cette classe, dans notre cas, définit l'implémentation personnalisée du FilteredRowSet . Nous avons ensuite appliqué ce filtre sur le résultat renvoyé par la requête de la base de données. Filtrage signifie limiter le nombre de lignes qui seront visibles. Par conséquent, nous limiterons ici le nombre d'enregistrements d'informations sur le livre en fonction du nom d'auteur sélectionné fourni.

Pour la pratique, voici les tables de base de données utilisées avec le code Java à venir.


Figure 1 : Table de base de données, livre


Figure 2 : Table de base de données, auteur


Figure 3 : Table de base de données, book_author

Le SimpleFilter la classe implémente le prédicat évaluent les méthodes pour implémenter notre filtre personnalisé.

package org.mano.example;
import javax.sql.RowSet;
import javax.sql.rowset.Predicate;
import java.sql.SQLException;
public class SimpleFilter implements Predicate {
   private String[] authors;
   private String colname = null;
   private int colno = -1;
   public SimpleFilter(String[] authors, String colname) {
      this.authors = authors;
      this.colno = -1;
      this.colname = colname;
   }
   public SimpleFilter(String[] authors, int colno) {
      this.authors = authors;
      this.colno = colno;
      this.colname = null;
   }
   @Override
   public Boolean evaluate(Object value, String colName) {
      if (colName.equalsIgnoreCase(this.colname)) {
         for (String author : this.authors) {
            if (author.equalsIgnoreCase((String)value)) {
              return true;
            }
         }
      }
      return false;
   }
   @Override
   public Boolean evaluate(Object value, int colNumber) {
      if (colNumber == this.colno) {
         for (String author : this.authors)
            if (author.equalsIgnoreCase((String)value)) {
               return true;
            }
         }
      }
      return false
   }
   @Override
   public Boolean evaluate(RowSet rs) {
      if (rs == null) return false;
      try {
         for (int i=0;i<authors.length;i++) {
            String al = null;
            if (this.colno> 0) {
                al = (String)rs.getObject(this.colno);
            } else if (this.colname != null) {
               al = (String)rs.getObject(this.colname);
            } else {
               return false;
            }
            if (al.equalsIgnoreCase(authors[i])) {
               return true;
            }
         }
      } catch (SQLException e) {
         return false;
      }
      return false;
   }
}

Cette classe est utilisée pour exécuter le SimpleRowSet classe de filtre. Notez comment nous avons utilisé FilteredRowSet pour filtrer les données dans l'application. Le traitement se produit au niveau de l'application plutôt qu'au niveau de la base de données SQL. En conséquence, nous pouvons implémenter une série de filtres et les appliquer sur le même jeu de résultats pour obtenir le résultat souhaité. Cela optimise les performances car nous n'avons pas à lancer plusieurs requêtes dans la base de données pour obtenir un résultat modifié. Au lieu de cela, nous pouvons appliquer plusieurs filtrages sur le résultat de la requête lancé une fois dans la base de données. L'application comporte deux phases importantes :

  • Nous créons un filtre qui définit les critères de filtrage des données. Cela se fait en implémentant le prédicat interface. Il peut y avoir plusieurs constructeurs acceptant différents ensembles d'arguments. De plus, le filtre peut contenir un tableau de evaluate() méthodes acceptant également différents ensembles d'arguments avec leur propre ensemble distinct d'implémentation.
  • Le FilteredRowSet la classe doit être instanciée pour obtenir l'effet désiré, ce que nous avons fait ici avec le applyFilter() méthode. Le FilteredRowSet utilise la classe de filtre personnalisée que nous avons fournie pour déterminer les enregistrements à afficher.
package org.mano.example;
import com.sun.rowset.FilteredRowSetImpl;
import javax.sql.RowSet;
import javax.sql.rowset.FilteredRowSet;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class DemoApp {
   private static final String DB_URL =
      "jdbc:mysql://localhost:3306/my_lib";
   private static final String DB_DRIVER =
      "com.mysql.cj.jdbc.Driver";
   private static final String DB_USERNAME =
      "root";
   private static final String DB_PASSWORD =
      "secret";
   public static Connection conn = null;
   public static FilteredRowSet filteredRowSet = null;
   public static void main(String[] args) {
      try {
         Class.forName(DB_DRIVER);
         conn = DriverManager.getConnection(DB_URL,
            DB_USERNAME,DB_PASSWORD);
         System.out.println("Database connection
            successful.");
         applyFilter();
      } catch (SQLException | ClassNotFoundException ex) {
         System.out.println(ex);
      } finally {
         if (conn != null) {
            try {
               conn.close();
            catch (SQLException ex) {
               ex.printStackTrace();
            }
         }
         if (filteredRowSet != null) {
            try {
               filteredRowSet.close();
            } catch (SQLException ex) {
               ex.printStackTrace();
            }
         }
      }
   }
   public static void applyFilter() {
      String[] arr = {"Donne", "Milton"};
      SimpleFilter aFilter = new SimpleFilter(arr, 3);
      try {
         filteredRowSet = new FilteredRowSetImpl();
         filteredRowSet.setCommand("SELECT title, f_name, l_name "
            + "FROM book_author BA, "
            + "author A, "
            + "book B "
            + "WHERE A.auth_id = BA.fk_author "
            + "AND B.book_id = BA.fk_book");
            filteredRowSet.execute(conn);
            System.out.println
               ("--------------------------------------------");
            System.out.println("Before applying any
               filter:");
            System.out.println
               ("--------------------------------------------");
            show(filteredRowSet);
            System.out.println
               ("--------------------------------------------");
            System.out.println("After applying
               filter :");
            System.out.println
               ("--------------------------------------------");
            filteredRowSet.beforeFirst();
            filteredRowSet.setFilter(aFilter);
            show(filteredRowSet);
      } catch (SQLException e) {
         e.printStackTrace();
      }
   }
   public static void show(RowSet rs) {
      try {
         while (rs.next()) {
            System.out.println(rs.getString(1) + " / "
               + rs.getString(2)
               + " "+rs.getString(3));
         }
      } catch (SQLException ex) {
         ex.printStackTrace();
      }
   }
}

Sortie

Database connection successful.
--------------------------------------------
Before applying any filter:
--------------------------------------------
Gulliver's Travels / Jonathan Swift

...

Ill Pensoroso / John Milton
Areopagitica / John Milton
--------------------------------------------
After applying filter:
--------------------------------------------
The Flea / John Donne
Holy Sonnet / John Donne
Paradise Lost / John Milton
Paradise Regained / John Milton
Ill Pensoroso / John Milton
Areopagitica / John Milton

Conclusion

Travailler avec un grand nombre de lignes renvoyées par une requête pose de nombreux problèmes. D'une part, les données récupérées occupent de la mémoire.

Il est toujours utile de les limiter en fonction du besoin et de la pertinence. Avec RowSet , nous pouvons les filtrer selon un critère sans faire de requêtes supplémentaires à la base de données. Cela facilite le travail avec les lignes de la base de données et optimise l'efficacité du code.