Skip to content
nablaone edited this page Jun 27, 2012 · 17 revisions

Gdzie jest moja tabela?

Czyli jak OneWeb SQL przyspiesza programowanie przy wciąż zmieniającym się schemacie bazy danych

Część 0: czego potrzebujemy

Zainstaluj na swoim komputerze następujące programy.

  1. Java 1.6 lub wyższa. Ustaw zmienną JAVA_HOME odpowiednio.
  2. PowerDesigner 16. Wersję ewaluacyjną można pobrać ze strony http://response.sybase.com/forms/PDV16-EA
  3. Eclipse (http://www.eclipse.org/downloads/)
  4. PostgreSQL 9.1 (http://www.enterprisedb.com/products-services-training/pgdownload). Razem z PostgreSQL instaluje się program pgAdmin. Jako locale wybierz ’Polish’.
  5. Tomcat 7.0 (http://tomcat.apache.org/download-70.cgi)
  6. OneWebSQL PD2Java 1.0.0 (http://OneWebSQL.com/download)

W instrukcjach dla użytkowników używamy następujących skrótów.

  • <PROJECT> – główny katalog aplikacji demo
  • <ONEWEBSQL HOME> – katalog, w którym jest zainstalowany OneWebSQL
  • <TOMCAT HOME> – katalog, w którym jest zainstalowany serwer Tomcat

Część 1: uruchomienie aplikacji

  1. Rozpakuj plik ZIP z aplikacją demo.
  2. Skonfiguruj projekt. Utwórz nowy projekt w Eclipse’ie File > New > Java Project ... i podaj lokalizację źródeł.new project Sprawdź, że katalogi src, generated-sources są folderami źródłowymi (Source Folders). Załóż katalog WEB-INF\classes i ustaw go jako folder docelowy (Output Folder).
  3. Skopiuj plik <ONEWEBSQL HOME>\onewebsql-runtime-1.0.0.jar do katalogu <PROJECT>\WEB-INF\lib. Skopiowany plik dodaj do Build Path.
  4. Do Build Path dodaj ścieżkę do pliku <TOMCAT HOME>\lib\servlet-api.jar.
  5. Przygotuj bazę danych. Uruchom program pgAdmin (został zainstalowany razem z PostgreSQL-em). Uruchom konsolę SQL.
  6. Stwórz użytkownika ’onewebsql’ z hasłem ’onewebsql’. create user onewebsql password ’onewebsql’;
  7. W ten sam sposób załóż bazę ’onewebsql’. create database onewebsql owner onewebsql;
  8. Połącz się z bazą danych jako użytkownik onewebsql.
  9. Uruchom skrypt zakładający tabele (<PROJECT>\database\create-schema.sql), wstaw dane początkowe (skrypt <PROJECT>\database\initial-data.sql).
  10. Skonfiguruj serwer Tomcat.
  11. kopiuj plik <PROJECT>\lib\postgresql-9.1-902.jdbc3.jar do <TOMCAT HOME>\lib.
  12. Do katalogu <TOMCAT HOME>\conf\Catalina\localhost skopiuj plik <PROJECT>\META-INF\context.xml. Zmień jego nazwę na onewebsql.xml.
  13. W pliku onewebsql.xml w atrybucie docBase podaj ścieżkę do projektu w Eclipse’ie.
  14. Uruchom serwer Tomcat: plik <TOMCAT HOME>\bin\startup.bat.
  15. W przeglądarce otwórz stronę http://localhost:8080/onewebsql.

Część 2: wprowadzenie

Będziemy pracować w prostej aplikacji WWW. Uruchom program PowerDesigner i otwórz plik <PROJECT>\database\Bookshop.pdm. Plik zawiera początkowy schemat bazy danych.

Dla każdej tabeli OneWebSQL generuje 3 pliki Javy:

  1. prostego beana reprezentującego wiersze tabeli,
  2. interfejs DAO, dający dostęp do tabeli,
  3. implementację DAO.

Jak to w życiu bywa, schemat bazy danych będzie się zmieniał. Dlatego każde ćwiczenie rozwiązuj w osobnej metodzie. Wtedy zobaczysz, w jaki sposób OneWebSQL pomaga poprawić kod aplikacji po zmianie schematu bazy danych.

Generowanie kodu

Użyjemy OneWebSQL-a w wersji standalone (jest też plugin do Maven 2). W Eclipse’ie wybierz Run > External Tools > External Tools Configurations... Utwórz nową konfigurację typu Program.

  1. Podaj javę jako program do uruchomienia.
  2. Jako katalog uruchomienia podaj swój projekt w Eclipse’ie.
  3. Podaj argumenty generatora:-jar <ONEWEBSQL_HOME>\onewebsql-pd2java-1.0.0.jar -classpath <ONEWEBSQL_HOME>\onewebsql-runtime-1.0.0.jar -model_sets database\Bookshop.pdm -java_output_dir generated-sources -java_default_package com.onewebsql.demo.or -dictionaries_dir database
  4. Zapisz konfigurację pod nazwą OneWebSQL. Uruchom generację.
  5. Odśwież projekt w Eclipse’ie.

Część 3: podstawowe API

  1. Obejrzyj kod klasy DemoServlet. Klasa zawiera szkielet aplikacji WWW. Główną metodą jest metoda doGet.
  2. Wypisz listę wszystkich książek. W metodzie doGet odkomentuj wywołanie metody exercise1. Przeczytaj kod metody exercise1. Do wypisania listy książek użyto metody getBookList() w interfejsie BookDAO.
  3. Uporządkuj wypisywaną listę książek według tytułu
    1. rosnąco,
    2. malejąco.
  4. Wykorzystaj metody z interfejsu BookDAO: getBookList(AExp orderByColumn) oraz `getBookList(AExp OrderByColumn, boolean ascending). Jako orderByColumn podaj stałą BookDAO.TITLE``.
  5. Wypisz listę książek o id większym od 2. Użyj metody getBookList(LExp whereClause) z interfejsu BookDAO. Warunek where powinien mieć postać BookDAO.NAZWA KOLUMNY.gt(2).
  6. Wypisz listę książek, których tytuły zaczynają się na literę A. Podpowiedź: użyj metody like.

Część 4: obiektowy język zapytań

  1. Nie wszystkie zapytania można wygenerować za pomocą metod get*List() z klas typu DAO. Istnieje również obiektowy język zapytań, w którym zapytania SQL można tworzyć bezpośrednio. Zapytanie jest reprezentowane przez obiekt klasy SelectQuery. Obiekt tego typu można podać, np. do metody getBookList(SelectQuery query) w interfejsie BookDAO. Poniższy diagram pokazuje, które klasy odpowiadają różnym częściom zapytania SQL.
  2. Wypisz listę wszystkich książek używając obiektowego języka zapytań. Zapytanie, które pobiera dane z tabeli book tworzymy za pomocą new SelectQuery(BookDAO.TABLE EXPRESSION)`. Zapytanie wykonujemy metodą getBookList(SelectQuery)w interfejsieBookDAO. SelectQuery query = new SelectQuery(BookDAO.TABLE_EXPRESSION);bookDAO.getBookList(query);``
  3. Powtórz poprzednie zapytania, używając obiektowego języka zapytań:
    1. Wypisz listę książek, których tytuły zaczynają się na literę A.
    2. Wypisz listę książek, które wydano po 2005 roku.
    3. Uporządkuj listę książek według roku wydania. Wykorzystaj metodę orderBy w klasie SelectQuery.
  4. Wypisz listę pierwszych 2 książek o ponad 100 stronach, w porządku alfabetycznym według tytułów. Wykorzystaj metodę limit(int) w klasie SelectQuery.

Część 5: zmiany, zmiany, zmiany

Wszyscy wiemy, że zmiany schematu bazy danych są nieuniknione. Tym razem zmiana jest prosta: kolumna number of pages nie będzie nam potrzebna i chcemy ją usunąć. Na tym przykładzie pokażemy, jak wygląda proces dewelopmentu aplikacji z OneWebSQL-em.

  1. Zmień schemat bazy danych. W schemacie bazy danych w PowerDesignerze (plik \database\Bookshop.pdm) w ta- beli book usuń kolumnę number of pages. Zapisz zmiany w PowerDesignerze.
  2. Wygeneruj skrypt SQL. Wygeneruj skrypt zakładający bazę danych (Database > Generate Database...).
  3. Wprowadź zmiany w bazie danych.
    1. W programie pgAdmin usuń wszystkie tabele w bazie onewebsql. Kliknij prawym klawiszem myszy na tabeli i wybierz Drop Cascaded.... Powtórz czynność dla sekwencji (węzeł Sequences).
    2. Uruchom wygenerowany przez PowerDesignera skrypt zakładający bazę danych. Kliknij ikonę Wykonaj dowolne zapytanie SQL. Wskaż lokalizację skryptu, a następnie kliknij przycisk Wykonaj zapytanie.
    3. Wstaw dane początkowe. Możesz użyć przygotowanego skryptu <PROJECT>\database\initial-data-without-number-of-pages.sql.
  4. Wygeneruj klasy OneWebSQL-a. Uruchom generator, który skonfigurowaliśmy w części 2. Odśwież projekt w Eclipse’ie.
  5. Popraw kod aplikacji. Zauważ, że niekompatybilne zmiany są sygnalizowane w postaci błędów kompilacji. Nie musisz zastanawiać się, co trzeba poprawić. Popraw kilka metod, pozostałe możesz usunąć lub zakomentować.

Część 6: złączenia tabel

  1. Wypisz listę książek, które należą do kategorii, których nazwa zaczyna się na literę P. Potrzebne zapytanie wykorzystuje dwie tabele: book i category. Możesz użyć:
  2. konstruktora klasy SelectQuery, który bierze listę tabel. Podaj odpowiedni warunek złączenia w metodzie where.
  3. konstruktora klasy SelectQuery, który bierze obiekt typu com.onewebsql.query.Join. Użyj odpowiedniej metody statycznej z klasy Join.
  4. Wypisz listę książek i nazwę kategorii, do której dana książka należy. Rekomendowany sposób to utworzenie odpowiedniego widoku i wygenerowanie dla niego klas OneWebSQL-a.
  5. W PowerDesignerze w panelu Toolbox wybierz ikonę View z sekcji Physical Diagram i kliknij w diagram. Zakończ dodawanie widoku klikając w prawy przycisk.
  6. Zmień nazwę widoku. Kliknij dwukrotnie na ikonę widoku. W oknie dialogowym wpisz nazwę: book_with_category_view.
  7. W zakładkę SQL Query wpisz treść zapytania SQL:
SELECT
book.book_id,
book.category_code,
category.category_name,
book.title,
book.publication_year
FROM
book JOIN category ON book.category_code = category.category_code;
  1. Wciśnij OK a następnie zapisz model PowerDesignera. W PowerDesignerze wygeneruj skrypt zakładający bazę danych. Skasuj tabele i sekwencje z bazy danych analogicznie jak w części 5. Następnie uruchom wygenerowany skrypt zakładający bazę danych i skrypt <PROJECT>\initial-data-book-with-category-view.sql. Wygeneruj klasy OneWebSQL-a i odśwież projekt w Eclipse’ie.
  2. Tę samą listę można wypisać inaczej, nie tworząc widoku, lecz korzystając z obiektowego języka zapytań.
  3. Utwórz obiekt SelectQuery reprezentujący zapytanie SQL z punktu 2c.
  4. Metody klas DAO w rodzaju getBookList(SelectQuery) przekształcają wyniki na obiekty klasy Book. Jeśli chcemy zwrócić obiekt innej klasy, musimy posłużyć się metodą selectObjectList(SelectQuery,RowHandler) i podać jej odpowiedni RowHandler.
public interface RowHandler<T> {
   T getObject(ResultSet resultSet) throws SQLException; 
 }

Obiekty typu com.onewebsql.util.jdbc.RowHandler przekształcają wyniki bazy danych na obiekty Javy.

  1. Przykładowy kod istniejącego RowHandlera.
 public class ListRowHandler<T> implements RowHandler<List<T>> {

   @SuppressWarnings("unchecked")
   public List<T> getObject(ResultSet resultSet) throws SQLException {
      int count = resultSet.getMetaData().getColumnCount();
      List<T> result = new ArrayList<T>(count);

      for (int i = 1; i <= count; i++) {
         Object obj = resultSet.getObject(i);
         if (resultSet.wasNull()) {
             obj = null;
         }
         result.add((T) obj);
      }
      return result;
   }
 }
  1. Użyj obiektu ListRowHandler<Object>, aby pobrać i wypisać wyniki zapytania utworzonego w punkcie 3a.

Część 7: zaawansowane zapytania

W obiektowym języku zapytań można tworzyć praktycznie dowolne zapytania SQL. Poniżej kilka przykładów.

  1. Napisz zapytanie zwracające informacje, w którym roku wydano ile książek. Przykładowe zapytanie SQL, które to robi.
SELECT publication_year, count(*)
FROM book
GROUP BY publication_year;

Kolumnę count(*) tworzy się tak: AExp.fun("count", AExp.exp("*")). Używamy tu statycznej metody com.onewebsql.query.AExp.fun(String,AExp). Klauzulę GROUP BY dodajemy wywołując metodę groupBy na obiekcie SelectQuery.

  1. Powtórz poprzednie ćwiczenie dla książek wydanych po roku 2005.
SELECT publication_year, count(*)
FROM book
GROUP BY publication_year;
HAVING publication_year > 2000;

Klauzulę HAVING dodajemy wywołując metodę having na obiekcie SelectQuery.

  1. Znajdź autora, który napisał najwięcej książek. Przykładowe zapytanie SQL, które to robi:
SELECT author.name
FROM author, book_author
WHERE author.author_id=book_author.author_id
GROUP BY author.author_id, author.name
HAVING count(*) >= ALL(
                      SELECT count(*)
                      FROM author,book_author
                      WHERE author.author_id = book_author.author_id
                      GROUP by author.author_id);

  1. Wylosuj dwie książki z listy wszystkich książek znajdujących się w bazie danych. Można to zrobić pobierając listę wszystkich książek z bazy danych. To rozwiązanie jest mało efektywne, jeśli danych w bazie jest dużo. Dlatego zrobimy to inaczej. Najpierw pobierz z bazy listę identyfikatorów książek. Posłuż się metodą selectObjectList z klasy BookDAO, jako RowHandler daj obiekt klasy SingleColumnRowHandler<Integer>. Z otrzymanej listy wylosuj dwa identyfikatory. Pobierz wylosowane książki posługując się wylosowanymi identyfikatorami.

Część 8: edycja danych

Część 9: słowniki

Clone this wiki locally