Database
 sql >> база данни >  >> RDS >> Database

Филтриране на данни с JDBC RowSet

Понякога заявките на приложения към база данни връщат голям брой редове. Въпреки че извлечените данни се кешират в ResultSet обект, често е твърде голям, за да се работи с тях. В резултат на това трябва да можем да ги филтрираме в различни набори от данни, за да ограничим видимите редове. Тази статия се задълбочава в описанието на аспекта на филтриране на JDBC RowSet с подходящи примери.

Общ преглед на RowSet

Набор редове е интерфейс, който допълва JDBC API за компонентен модел на JavaBeans. Той предоставя набор от свойства, които позволяват на неговия екземпляр да бъде конфигуриран за свързване към JDBC източник на данни. Набор от редове instance се използва основно за извличане на данни от източника на данни. Методите за настройка на този интерфейс се използват за попълване на параметрите на свойството на командата на SQL заявка, която след това се използва за извличане на записи от релационната база данни. Тъй като RowSet се придържа към компонентния модел на JavaBean, той поддържа събития на JavaBean. Тези събития се използват за уведомяване на други компоненти за събития, като например промяна на стойността в набор от редове. Тъй като RowSet интерфейсът е проектиран като слой над JDBC драйвера, той е отворен за персонализирана реализация. Тази свобода дава възможност на доставчика да изработи собствено фино настроено изпълнение и да го изпрати с продукта JDBC.

FilteredRowSet

FilteredRowSet е интерфейсно разширение на RowSet семейство. Има референтна реализация на този интерфейс, наречена FilteredRowSetImpl клас. За предоставяне на персонализирана реализация на FilteredRowSet интерфейс, може да се разшири FilteredRowSetImpl клас или използвайте FilteredRowSet интерфейс според вашите изисквания. В някои случаи трябва да приложим някаква форма на филтриране върху съдържанието, което RowSet извлича. Едно просто възможно решение е да се осигури език за заявки за всички RowSet реализации. Но тогава това не е жизнеспособен подход, защото RowSet е изграден с идеята за отделен лек компонент. Това ще направи обекта тежък и ще противоречи на неговия принцип на проектиране. Нуждаем се от подход, който отговаря на необходимостта, но не инжектира тежък език за заявки заедно с логиката на обработка на филтриране. JDBC FilteredRowSet стандартната реализация разширява RowSet чрез подинтерфейсите като CachedRowSet и WebRowSet съответно. FilteredRowSet може да манипулира курсора чрез набора от защитени методи за манипулиране на курсора, предоставени от CachedRowSet интерфейс. Тези методи могат да бъдат отменени според изискванията и да помогнат при филтриране на RowSet съдържание.

Бърз пример

Ето пример за илюстриране как FilteredRowSet се използва за съхраняване на съдържанието, върнато от заявката, задействана към базата данни. Резултатът от заявката се филтрира според конфигурацията, приложена към FilteredRowset изпълнение. Това дефинира видимото съдържание или редовете, които ни интересуват от резултата, върнат от заявката. В следващия пример създадохме филтърен клас, наречен SimpleFilter . Този клас в нашия случай дефинира персонализираната реализация на FilteredRowSet . След това приложихме този филтър към резултата, върнат от заявката за база данни. Филтриране означава ограничаване на броя на редовете, които ще бъдат видими. Ето защо тук ще ограничим броя на записите с информация за книгата според предоставеното име на избрания автор.

За практически, по-долу са таблиците на базата данни, използвани с предстоящия Java код.


Фигура 1: Таблица в базата данни, книга


Фигура 2: Таблица в базата данни, автор


Фигура 3: Таблица в базата данни, book_author

SimpleFilter клас имплементира Предикат Методи за оценка за прилагане на нашия персонализиран филтър.

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

Този клас се използва за изпълнение на SimpleRowSet филтър клас. Обърнете внимание как използвахме FilteredRowSet за филтриране на данни в приложението. Обработката се извършва на ниво приложение, а не на ниво SQL база данни. В резултат на това можем да внедрим серия от филтри и да ги приложим към същия набор от резултати, за да получим желания резултат. Това увеличава производителността, защото не е нужно да задействаме множество заявки към базата данни, за да получим модифициран резултат. Вместо това можем да приложим многократно филтриране върху резултата от заявката, задействан веднъж към базата данни. Приложението има две важни фази:

  • Създаваме филтър, който определя критериите за филтриране на данните. Това става чрез внедряване на Предикат интерфейс. Може да има множество конструктори, приемащи различен набор от аргументи. Също така филтърът може да съдържа масив от evaluate() методи също така приемат различен набор от аргументи със собствен отделен набор от имплементации.
  • FilteredRowSet класът трябва да бъде инстанциран, за да се получи желания ефект, нещо, което направихме тук с applyFilter() метод. FilteredRowSet използва персонализирания клас на филтъра, който сме предоставили, за да определи записите, които да бъдат прегледани.
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();
      }
   }
}

Изход

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

Заключение

Работата с голям брой редове, върнати от заявка, има много проблеми. От една страна, извлечените данни заемат памет.

Винаги помага ограничаването им според необходимостта и уместността. С RowSet , можем да ги филтрираме според критерий, без да правим допълнителни заявки за база данни. Това го прави по-управляемо за работа с редове в базата данни и повишава ефективността на кода.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Мониторинг на синхронизация на реплики на групата наличност

  2. Топ 9 системи за управление на бази данни за шаблони на Joomla

  3. Как да генерирате DB тестови данни

  4. Пространството за таблици SYSMMGMTDATA е ПЪЛНО в хранилището за управление на грид инфраструктурата (MGMTDB)

  5. Съвети за управление на архивиране за TimescaleDB