Adatbázis-programozás


A Java nyelv hálózati lehetőségei miatt ideálisan megfelel kliens-szerver architektúrájú adatbáziskezelő programok létrehozására. Ezért felmerült az igény, hogy a Java programok kommunikálni tudjanak a legkülönfélébb adatbázisokkal is. Ezen kommunikáció lehetőségét a JDBC biztosítja.

  1. Egyszerű (DISTINCT) felhasználói SQL típus
  2. Ezen SQL adattípus tulajdonképp egy egyszerű SQL alaptípus megfelelően paraméterezett változata. Példák:
    CREATE TYPE RÖVIDNÉV AS CHAR(20);
    CREATE TYPE PÉNZ AS NUMERIC(10,2);
    

  3. Struktúrált (STRUCT) felhasználói SQL típus
  4. Ezen SQL adattípus más SQL típusokból összetevődő struktúrát ír le. Példák:
    CREATE TYPE LAKHELY 
         (
                 AJTÓ VARCHAR(20),
                 HÁZSZÁM NUMERIC(6),
                 UTCA VARCHAR(100), 
                 VÁROS VARCHAR(50),
                 IRÁNYÍTÓSZÁM CHAR(8),
                 TULAJDONOS REF(SZEMÉLY)
         );
    CREATE TYPE TELJESNÉV
         (
                 VEZETÉKNÉV VARCHAR(50),
                 KERESZTNÉV VARCHAR(50)
         );
    CREATE TYPE SZEMÉLY 
         (
                 NÉV TELJESNÉV,
                 CÍM REF(LAKHELY),
                 TELEFON VARCHAR(20),
                 FOTÓ BLOB
         );
    

  5. Felhasználói SQL adattípusok Java megfeleltetése
  6. A leírtak szemléltetésére tekintsük az előző két példában definiált felhasználói SQL típusok Java reprezentációit. A Dolgozó osztály egyben példa arra is, hogy hogyan lehet a reprezentáló osztályokkal az SQL öröklődési hierarhiát követni. Ehhez az SQL típust a következőképp definiáltuk:
    CREATE TYPE SZEMÉLY AS OBJECT (...);
    CREATE TYPE DOLGOZÓ AS OBJECT EXTENDS SZEMÉLY (BÉR PÉNZ);
    
    Már csak a típusmegfeleltetés megadása maradt hátra:
    Connection con=...
    try {
        java.util.Map map = con.getTypeMap();
        map.put("RÖVIDNÉV", Class.forName("Rövidnév"));
        map.put("PÉNZ", Class.forName("Pénz"));
        map.put("LAKHELY", Class.forName("Lakhely"));
        map.put("TELJESNÉV", Class.forName("Teljesnév"));
        map.put("SZEMÉLY", Class.forName("Személy"));
        map.put("DOLGOZÓ", Class.forName("Dolgozó"));
    } catch (ClassNotFoundException ex) {}
    

  7. Eredményfeldolgozás
  8. A következő kódrészlet biztosítja egy végrehajtott SQL utasítás összes visszaadott eredménykomponensének feldolgozását:
        Connection con = DriverManager.getConnection(url, "uid", "password");
                                                    //adatbáziskapcsolat létrehozása
        Statement stmt = con.createStatement();       //utasításobjektum létrehozása
    
        stmt.execute(SQL_utasítás);                      //SQL utasítás végrehajtása
        int rowCount;
        while (true)  {
          rowCount = stmt.getUpdateCount();
          if (rowCount >= 0) {                                   //volt sormódosítás
            System.out.println("Megváltozott sorok száma = " + rowCount);
            stmt.getMoreResults();        //következő eredménykomponens feldolgozása
            continue;
          }
          ResultSet rs = stmt.getResultSet();                   //eredménytábla volt
          if (rs != null) {                             //eredménytábla feldolgozása
             ...
             stmt.getMoreResults();       //következő eredménykomponens feldolgozása
             continue;
          }
          break;                                      //nincs több eredménykomponens
        }
    

  9. Példa kötegelt végrehajtásra
  10. int[] updateCounts;
    Connection con=...
    try {
        con.setAutoCommit(false);
    
        Statement stmt = con.createStatement();
        stmt.addBatch("CREATE TABLE NEVEK OF TELJESNÉV");
        stmt.addBatch("INSERT INTO NEVEK VALUES ('Gábor', 'Dénes')");
        stmt.addBatch("INSERT INTO NEVEK VALUES ('Máté', 'Barbara')");
        stmt.addBatch("INSERT INTO NEVEK VALUES ('Csilla', 'Péter')");
        stmt.addBatch("DELETE FROM NEVEK");
        updateCounts = stmt.executeBatch(); // {0, 1, 1, 1, 3}
    
        PreparedStatement pstmt = con.prepareStatement(
                      "INSERT INTO NEVEK VALUES (?, ?)");
    
        pstmt.setString(1, "Névtelen");
        for (int i=1; i<=10; i++) {
            pstmt.setString(2, "Felhasználó"+i );
            pstmt.addBatch();
        }
        updateCounts = pstmt.executeBatch(); // {1,1,1,1,1,1,1,1,1,1}
    
        stmt.addBatch("SELECT * FROM NEVEK");     // itt még nem, de
        updateCounts = stmt.executeBatch(); // itt Exception!!!!
        
    } catch (BatchUpdateException bue) {
            System.err.println("BatchUpdateException: " + bue.getMessage());
            System.err.println("SQLState:  " + bue.getSQLState());
            System.err.println("ErrorCode:  " + bue.getErrorCode());
            System.err.println("Sikeres végrehajtások sormódosítási számai:");
            updateCounts = bue.getUpdateCounts();
            for (int i=1; i<=updateCounts.length; i++) {
                 System.err.println("\t" + i + ".: " + updateCounts[i]);
            }
    } catch (SQLException e) {
            System.err.println("SQLException: " + e.getMessage());
            System.err.println("SQLState:  " + e.getSQLState());
            System.err.println("ErrorCode:  " + e.getErrorCode());
    }
    

  11. Példa
  12. A következő példa egy általános JDBC adatbázis-elérési felületet nyújt. Használható mind alkalmazásként, mind appletként, persze ilyenkor figyelembe kell venni az ismertetett megkötéseket.