sql >> Database >  >> RDS >> Database

Gegevens filteren met de JDBC RowSet

Soms retourneren toepassingsquery's naar een database een groot aantal rijen. Hoewel opgehaalde gegevens in de cache worden opgeslagen in de ResultSet object, is het vaak te groot om ermee te werken. Als gevolg hiervan moeten we ze in verschillende gegevenssets kunnen filteren om de zichtbare rijen te beperken. Dit artikel gaat dieper in op het filteraspect van JDBC RowSet met passende voorbeelden.

Een overzicht van RowSet

Rijset is een interface die een aanvulling vormt op de JDBC API voor het JavaBeans-componentmodel. Het biedt een set eigenschappen waarmee het exemplaar kan worden geconfigureerd om verbinding te maken met een JDBC-gegevensbron. Een Rijset instance wordt voornamelijk gebruikt om gegevens uit de gegevensbron op te halen. De setter-methoden van deze interface worden gebruikt om de parameters van de opdrachteigenschap van een SQL-query te vullen, die vervolgens wordt gebruikt om records op te halen uit de relationele database. Omdat RowSet houdt zich aan het JavaBean-componentmodel, het ondersteunt JavaBean-evenementen. Deze gebeurtenissen worden gebruikt om andere componenten op de hoogte te stellen van gebeurtenissen, zoals een wijziging van de waarde op een rijenset. Omdat de RowSet interface is ontworpen als een laag boven het JDBC-stuurprogramma en staat open voor aangepaste implementatie. Deze vrijheid stelt de verkoper in staat om hun eigen verfijnde effectuation te fabriceren en deze met het JDBC-product te verzenden.

De FilteredRowSet

De FilteredRowSet is een interface-uitbreiding van de RowSet familie. Er is een referentie-implementatie van deze interface, genaamd de FilteredRowSetImpl klas. Om een ​​aangepaste implementatie van de FilteredRowSet te bieden interface, kan men ofwel de FilteredRowSetImpl . uitbreiden class of gebruik de FilteredRowSet interface volgens uw vereiste. In sommige gevallen moeten we een vorm van filtering toepassen op de inhoud die RowSet haalt. Een eenvoudige mogelijke oplossing is om een ​​querytaal te bieden voor alle RowSet implementaties. Maar dit is geen haalbare aanpak omdat RowSet is gebouwd met het idee van een losgekoppeld lichtgewicht onderdeel. Dit zou het object zwaar maken en indruisen tegen het ontwerpprincipe. We hebben een aanpak nodig die tegemoet komt aan de behoefte, maar die geen zware querytaal injecteert samen met de verwerkingslogica van filteren. De JDBC FilteredRowSet standaard implementatie breidt RowSet uit via de subinterfaces zoals CachedRowSet en WebRowSet respectievelijk. De FilteredRowSet kan de cursor manipuleren via de set van beschermde methoden voor cursormanipulatie geleverd door de CachedRowSet koppel. Deze methoden kunnen worden overschreven volgens de vereisten en helpen bij het filteren van RowSet inhoud.

Een snel voorbeeld

Hier is een voorbeeld om te illustreren hoe FilteredRowSet wordt gebruikt om de inhoud op te slaan die is geretourneerd door de query die naar de database is verzonden. Het resultaat van de zoekopdracht wordt gefilterd volgens de configuratie die is toegepast op de FilteredRowset implementatie. Dit definieert de zichtbare inhoud of de rijen waarin we geïnteresseerd zijn op basis van het resultaat dat door de query wordt geretourneerd. In het volgende voorbeeld hebben we een filterklasse gemaakt met de naam SimpleFilter . Deze klasse definieert in ons geval de aangepaste implementatie van de FilteredRowSet . Vervolgens hebben we dit filter toegepast op het resultaat van de databasequery. Filteren betekent het beperken van het aantal rijen dat zichtbaar zal zijn. Daarom beperken we hier het aantal records met boekgegevens op basis van de opgegeven auteursnaam.

Voor hands-on volgen hieronder de databasetabellen die worden gebruikt met de aankomende Java-code.


Figuur 1: Databasetabel, boek


Figuur 2: Databasetabel, auteur


Figuur 3: Databasetabel, book_author

De SimpleFilter class implementeert het Predikaat 's evalueren methoden om ons aangepaste filter te implementeren.

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;
   }
}

Deze klasse wordt gebruikt om de SimpleRowSet . uit te voeren klasse filteren. Merk op hoe we FilteredRowSet hebben gebruikt om gegevens in de toepassing te filteren. De verwerking vindt plaats op toepassingsniveau in plaats van op SQL-databaseniveau. Als gevolg hiervan kunnen we een reeks filters implementeren en deze toepassen op dezelfde resultatenset om het gewenste resultaat te verkrijgen. Dit maakt gebruik van de prestaties omdat we niet meerdere query's naar de database hoeven te sturen om een ​​aangepast resultaat te krijgen. In plaats daarvan kunnen we meerdere filters toepassen op het queryresultaat dat eenmaal naar de database is verzonden. De applicatie kent twee belangrijke fasen:

  • We maken een filter waarin de criteria voor het filteren van de gegevens worden vastgelegd. Dit wordt gedaan door het Predicaat . te implementeren koppel. Er kunnen meerdere constructeurs zijn die verschillende reeksen argumenten accepteren. Het filter kan ook een array van evaluate() . bevatten methoden accepteren ook verschillende reeksen argumenten met hun eigen specifieke implementatiereeks.
  • De FilteredRowSet class moet worden geïnstantieerd om het gewenste effect te verkrijgen, iets wat we hier hebben gedaan met de applyFilter() methode. De FilteredRowSet gebruikt de aangepaste filterklasse die we hebben geleverd om te bepalen welke records moeten worden bekeken.
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();
      }
   }
}

Uitvoer

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

Conclusie

Werken met een groot aantal rijen die uit een query worden geretourneerd, levert veel problemen op. Ten eerste nemen de opgehaalde gegevens geheugen in beslag.

Het helpt altijd om ze te beperken volgens de behoefte en relevantie. Met RowSet , kunnen we ze filteren op een criterium zonder aanvullende databaseverzoeken te doen. Dit maakt het beter beheersbaar om met databaserijen te werken en maakt gebruik van de efficiëntie van de code.


  1. MySQL DISTINCT op een GROUP_CONCAT()

  2. SET SQLBLANKLINES:Lege regels toestaan ​​in SQLcl &SQL*Plus

  3. Tabellen maskeren en referentiële integriteit behouden?

  4. Extra rijen krijgen - Nadat u lid bent geworden van de 3 tafels met behulp van Left Join