JDBC (Java Database Conectivity) je súčasťou J2EE (podobne ako servlety), je to rozhranie na prácu s databázovými systémami. Existuje niekoľko typov JDBC rozhraní. Použitie tohto rozhrania však prináša určité nevýhody, ktoré je možné kompenzovať použitím tzv. connection poolingu s využitím JNDI (Java Naming and Directory Interface) v spojitosti s databázami. Cieľom dnešného článku bude na jednoduchých príkladoch načrtnúť niektoré z možností práce s databázami prostredníctvom servletov pri vývoji webovských aplikácií.

V tomto článku nebudeme rozoberať JDBC ako také. Jednak by to vyšlo na celý seriál a jednak na túto tému existuje veľa zdrojov, napríklad vynikajúci JDBC tutoriál na stránkach firmy Sun (pozri aj Úvod do JDBC). To isté platí aj pre technológiu JNDI. Ak máte záujem o ďalšie informácie, kliknite si na JNDI tutoriál.

Ako prvé sa budeme venovať použitiu JDBC. Prejdeme si základné kroky potrebné na pripojenie k databázam a vytvoríme si objekty, pomocou ktorých potom môžeme s tabuľkami pracovať. A pozrieme sa tiež na výhody a nevýhody tejto technológie.

JDBC – použitie

Čo sa týka použitia JDBC v spojitosti so servletmi (prípadne JSP), je veľmi podobné ako pri ostatných typoch aplikácií vytvorených v jazyku Java. To znamená, že ak máte s týmto rozhraním už skúsenosti, nemal by byť pre vás problém vytvoriť pripojenie a pracovať s databázou pomocou servletov. Otázka je, ako to spraviť čo najefektívnejšie, bez zbytočného zaťažovania zdrojov, s ohľadom na prenositeľnosť aplikácie, jej údržbu a podobne. Kľúčovou otázkou v prípade servletov je, kde umiestniť kód vykonávajúci pripojenie k databázovému serveru. Máme dve možnosti, buď do metódy init() alebo do doGet(). Ani jedno riešenie nie je ideálne. Začneme tým, že si v záujme ľahkej prenositeľnosti vytvoríme inicializačné parametre v súbore web.xml:

<web-app>
  <servlet>
    <servlet-name>DBServlet</servlet-name>
    <servlet-class>interval.DBServlet</servlet-class>
        <init-param>
            /* Na vytvorenie konekcie na konkrétny databázový server potrebujete tzv. driver.
             Je to balíček tried dodávaný buď dodávateľom servera alebo treťou stranou.
             Použitý driver je pre server Informix. Od toho sa odvíja aj tvar URL.
             „org.gjt.mm.myslql.Driver“ — driver pre MySql.
             „sun.jdbc.odbc.JdbcOdbcDriver“ — tzv. jdbc-odbc premostenie, napr. pre MS SQL.
             „com.ibm.db2.jdbc.app.DB2Driver“ — driver pre IBM DB2 server.
             Na server Tomcat sa driver umiestňuje do /common/lib adresára. */

            <param-name>driver</param-name>
            <param-value>com.informix.jdbc.IfxDriver</param-value>
        </init-param>
        <init-param>
            /* URL je informácia obsahujúca IP a port servera, názov databázy a názov servera.
            Jej tvar a obsah je platformovo závislý. Prezrite si dokumentáciu k vášmu driveru. */
            <param-name>url</param-name>
            <param-value>
                jdbc:informix-sqli://IP:port/database:INFORMIXSERVER=ol1
            </param-value>
        </init-param>
        <init-param>
            //prihlasovacie meno
            <param-name>user</param-name>
            <param-value>username</param-value>
        </init-param>
        <init-param>
            //prihlasovacie heslo
            <param-name>paswd</param-name>
            <param-value>userpaswd</param-value>
        </init-param>
  </servlet>
</web-app>

Všetky tieto parametre je možné vložiť natvrdo do kódu servletu, ale to nie je moc rozumné. Pokiaľ však uvažujete, že DBservlet bude nasadený výlučne na jednej konkrétnej platforme, môžete vyššie uvedený postup obísť. Keďže heslo na pripojenie k databáze nie je šifrované, predpokladá sa, že deskriptor aplikácie nie je (z dôvodu bezpečnosti) voľne dostupný pre kohokoľvek.

Teraz uvediem niekoľko komentovaných výsekov kódu, ktoré načrtnú spôsob použitia JDBC. Uvediem len dôležité pasáže, teda žiadne spracovanie získaných údajov, ich prezentácia a pod. sa nekoná. Ponúkam vám aj farebnú verziu zdrojového kódu. To už nechám na vás.

package interval;
import javax.servlet.*;
import javax.servlet.http.*;
import java.sql.*;
public class DBServlet extends HttpServlet {
  // pripravím si „globálne“ premenné.
  private String driver;
  private String url;
  private String user;
  private String paswd;
  private Connection con;
  public void init(ServletConfig conf)
              throws ServletException {
    /* z web.xml postupne získam jednotlivé parametre
    potrebné na pripojenie k databáze */

    driver = conf.getInitParameter(„driver“);
    url = conf.getInitParameter(„url“);
    user = conf.getInitParameter(„user“);
    paswd = conf.getInitParameter(„paswd“);
  }
  public void doGet(HttpServletRequest request, HttpServletResponse response)
              throws ServletException, IOException {
    try {
      /* vytvoríme objekt databázového JDBC drivera
      Tento driver nie je súčasťou Java API, */

      Class.forName(driver);
    }
    catch (ClassNotFoundException e) {}
    try {
      // naplnenie objekt Connection, pripojíme sa k DB serveru.
      con = DriverManager.getConnection(url,user,paswd);
      /* vytvorenie objekt Statement, prostredníctvom ktorého
      môžeme posielať SQL dotazy*/

      Statement stm = con.createStatement();
      // vytvorenie SQL dotazu
      String sql = „SELECT * FROM TABLE“;
      // vytvorenie objektu ResultSet
      ResultSet rs = stm.executeQuery(sql);
      /* objekt rs obsahuje tabuľku údajov vrátenú metódou executeQuery(sql)
      Tento objekt je možné v cykle prechádzať a získavať jednotlivé hodnoty.*/

      stm.close();
    }
    catch (SQLException e) {}
    finally {
      // ukončenie pripojenia k DB serveru.
      try { con.close(); } catch (Exception e) {}
    }
  }
}

Uvedený príklad samozrejme nie je kompletný, zobrazuje len dôležité pasáže. Rozhranie JDBC obsahuje pochopiteľne oveľa viac rôznych tried, metód a konštánt. Obsahuje napr. podporu transakcií, uložených procedúr, vytvárania predpripravených príkazov (tzv. prepared statements), skrolovateľné kurzory a pod.

Skúsme si trochu teoreticky rozobrať uvedený príklad. Načítanie drivera, pripojenie k DB, vytvorenie SQL dopytu, získanie a spracovanie výsledkov vrátane odchytenia výnimiek a ukončenia pripojenia, to všetko sa zrealizovalo v metóde doGet(). Znamená to, že pre každý jeden request sa musí vykonať celá táto procedúra. No a to je samozrejme náročné na výkon a pamäťové prostriedky servera. Pri veľkom množstve súčasných požiadaviek sa teda rapídne zvýši doba odozvy. Sú tu aj ďalšie riziká. Napríklad DB server môže byť nastavený tak, že akceptuje len určité množstvo súčasných pripojení. Je jasné, že by sa našlo ešte niekoľko ďalších obmedzení, ktoré moc nehovoria v prospech takého použitia JDBC ako som uviedol.

Na riešenie tohto problému (vytváranie veľkého množstva DB konekcií) existuje tzv. connection pooling. Teda niečo ako zdieľanie DB pripojenia. Funguje na princípe implementácie „sprostredkovateľskej triedy“. Táto trieda potom poskytuje prístup k databáze pre klientov a zároveň vytvára nové, resp. manažuje existujúce spojenia. Connection pooling je technológia podporovaná veľkým množstvom existujúcich alebo pripravovaných JDBC driverov. Špecifikácia J2EE 1.3 zahrnula do JDBC aj triedu javax.sql.DataSource, prostredníctvom ktorej je možné vytvoriť a používať zdieľanie pripojení k DB.

Tomcat prevzal J2EE špecifikáciu a používa triedu DataSource za účelom zabezpečenia connection poolingu. V druhej časti tohto článku si ukážeme, ako realizovať a využívať connection pooling s podporou JNDI na platforme Tomcat.

Starší komentáře ke článku

Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.

Žádný příspěvek v diskuzi

Odpovědět