sql >> Database teknologi >  >> RDS >> Database

Filtrering af data med JDBC RowSet

Nogle gange returnerer applikationsforespørgsler til en database et stort antal rækker. Selvom hentede data cachelagres i Resultatsættet objekt, er det ofte for stort til at arbejde med dem. Som et resultat skal vi være i stand til at filtrere dem i forskellige datasæt for at begrænse de synlige rækker. Denne artikel fordyber sig i at beskrive filtreringsaspektet af JDBC RowSet med passende eksempler.

En oversigt over RowSet

Rækkesæt er en grænseflade, der komplementerer JDBC API for JavaBeans komponentmodellen. Det giver et sæt egenskaber, der gør det muligt at konfigurere dens instans til at oprette forbindelse til en JDBC-datakilde. Et RowSet instans bruges primært til at hente data fra datakilden. Setter-metoderne for denne grænseflade bruges til at udfylde parametrene for kommandoegenskaben for en SQL-forespørgsel, som derefter bruges til at hente poster fra relationsdatabasen. Fordi RowSet overholder JavaBean-komponentmodellen, den understøtter JavaBean-begivenheder. Disse hændelser bruges til at underrette andre komponenter om hændelser, såsom en ændring af værdi på et rækkesæt. Fordi RowSet grænsefladen er designet som et lag over JDBC-driveren, den er åben for tilpasset implementering. Denne frihed giver leverandøren mulighed for at fremstille deres egen finjusterede effektuering og sende den sammen med JDBC-produktet.

Filtered RowSet

FilteredRowSet er en grænsefladeudvidelse af RowSet familie. Der er en referenceimplementering af denne grænseflade, kaldet FilteredRowSetImpl klasse. At levere en tilpasset implementering af FilteredRowSet grænsefladen, kan man enten udvide FilteredRowSetImpl klasse eller brug FilteredRowSet interface efter dit krav. I nogle tilfælde er vi nødt til at anvende en form for filtrering på indholdet, der RowSet henter. En simpel mulig løsning er at levere et forespørgselssprog for alle RowSet implementeringer. Men så er dette ikke en holdbar tilgang, fordi RowSet er bygget med ideen om en frakoblet letvægtskomponent. Dette ville gøre objektet tungt og gå imod dets designprincip. Vi har brug for en tilgang, der imødekommer behovet, men som ikke injicerer tungt forespørgselssprog sammen med filtreringslogikken. JDBC FilteredRowSet standardimplementering udvider RowSet gennem undergrænseflader såsom CachedRowSet og WebRowSet henholdsvis. FilteredRowSet kan manipulere markøren gennem det sæt af beskyttede markørmanipulationsmetoder leveret af CachedRowSet interface. Disse metoder kan tilsidesættes i henhold til krav og hjælp, mens du filtrerer RowSet indhold.

Et hurtigt eksempel

Her er et eksempel for at illustrere, hvordan FilteredRowSet bruges til at gemme indholdet, der returneres af forespørgslen til databasen. Resultatet af forespørgslen filtreres i overensstemmelse med den konfiguration, der anvendes på FilteredRowset implementering. Dette definerer det synlige indhold eller de rækker, som vi er interesserede i, fra resultatet returneret af forespørgslen. I det følgende eksempel har vi oprettet en filterklasse kaldet SimpleFilter . Denne klasse definerer i vores tilfælde den tilpassede implementering af FilteredRowSet . Vi anvendte derefter dette filter på resultatet returneret fra databaseforespørgslen. Filtrering betyder begrænsning af antallet af rækker, der vil være synlige. Derfor vil vi her begrænse antallet af bogoplysninger i henhold til det angivne valgte forfatternavn.

Følgende er databasetabellerne, der bruges sammen med den kommende Java-kode.


Figur 1: Databasetabel, bog


Figur 2: Databasetabel, forfatter


Figur 3: Databasetabel, bogforfatter

SimpleFilter klasse implementerer prædikatet 's evaluerer metoder til at implementere vores tilpassede filter.

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

Denne klasse bruges til at udføre SimpleRowSet filter klasse. Bemærk, hvordan vi har brugt FilteredRowSet for at filtrere data i applikationen. Behandlingen foregår på applikationsniveau snarere end på SQL-databaseniveau. Som et resultat kan vi implementere en række filtre og anvende dem på det samme resultatsæt for at opnå det ønskede resultat. Dette udnytter ydeevnen, fordi vi ikke behøver at sende flere forespørgsler til databasen for at få et ændret resultat. I stedet kan vi anvende flere filtreringer på forespørgselsresultatet, der blev udløst én gang til databasen. Ansøgningen har to vigtige faser:

  • Vi opretter et filter, som fastlægger kriterierne for filtrering af dataene. Dette gøres ved at implementere prædikatet interface. Der kan være flere konstruktører, der accepterer forskellige sæt af argumenter. Filteret kan også indeholde en matrix af evaluate() metoder, der også accepterer forskellige sæt af argumenter med deres eget særskilte sæt af implementering.
  • Filtered RowSet klasse skal instansieres for at opnå den ønskede effekt, noget som vi har gjort her med applyFilter() metode. FilteredRowSet bruger den tilpassede filterklasse, vi har leveret til at bestemme, hvilke poster der skal ses.
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();
      }
   }
}

Output

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

Konklusion

Arbejde med et stort antal rækker returneret fra en forespørgsel har mange problemer. For det første optager hentede data hukommelse.

Det hjælper altid at begrænse dem efter behov og relevans. Med RowSet , kan vi filtrere dem efter et kriterium uden at foretage yderligere databaseanmodninger. Dette gør det mere overskueligt at arbejde med databaserækker og udnytter effektiviteten af ​​koden.


  1. Hvad er den ideelle datatype at bruge, når du gemmer breddegrad/længdegrad i en MySQL-database?

  2. Hvordan genererer man DDL programmatisk fra Oracle-databasen?

  3. SYSTIMESTAMP Funktion i Oracle

  4. SQL SELECT-syntaks – Listet efter DBMS