1 / 38

4.3. Tietokantojen ohjelmointirajapinnat

4.3. Tietokantojen ohjelmointirajapinnat. Engl. API (Application Programming Interface). Ohj.kielen täydennys moduuli-/luokkakirjastoilla SQL/CLI (Call-Level Interface), osa SQL-standardia vuodesta 2003. Tunnetuimpia rajapintoja:

dionne
Download Presentation

4.3. Tietokantojen ohjelmointirajapinnat

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 4.3. Tietokantojen ohjelmointirajapinnat • Engl. API (Application Programming Interface). • Ohj.kielen täydennys moduuli-/luokkakirjastoilla • SQL/CLI (Call-Level Interface), osa SQL-standardia vuodesta 2003. • Tunnetuimpia rajapintoja: • ODBC (Open DataBase Connectivity):SQL/CLI-pohjainen, Microsoftin kehittämä, yleinen C, C++, C# ja Visual Basic –kielten yhteydessä. • JDBC (‘Java DataBase Connectivity’): Sun Micro-systemsin piirissä kehitetty API-kirjasto Javalle. 4-3-OhjRajapinnat Teuhola 2012

  2. JDBC: Yleistä • JDBC on Javan luokka-/rajapintakirjastomääritys, joka mahdollistaa SQL-lauseiden suorituksen Javasta käsin (lauseet metodien parametreina). • Vastaa dynaamista, sulautettua SQL:ää. • Ero SQLJ:hin: JDBC ei ole kielen laajennus,joten standardi Java-kääntäjä riittää. • Hyvin tuettu (‘teollisuusstandardi’) • Javan etu: siirrettävyys (portability). • JDBC:tä käyttävä ohjelma on lähes riippumaton siitä, mikä tietokantajärjestelmä on käytössä (voidaan vaihtaa) 4-3-OhjRajapinnat Teuhola 2012

  3. JDBC-ajuri • JDBC-API toimii sovellusohjelmien rajapintana. Yhteydet tietokantaan hoitaa JDBC-ajuri (driver). • Kuhunkin tietokantajärjestelmään on oma ajurinsa; saatavana järjestelmän toimittajalta, ks. esim. http://jdbc.postgresql.org/download.html. • Ajuri on jar-paketti (esim. postgresql.jar), joka sijoitetaan haluttuun hakemistopolkuun. Polku pitää määritellä CLASSPATH-ympäristömuuttu-jassa. 4-3-OhjRajapinnat Teuhola 2012

  4. Java-ohjelma Asiakas JDBC-ajuri Tietokannanhallintajärjestelmä Palvelin Tietokanta Asiakas/palvelin-arkkitehtuuri 4-3-OhjRajapinnat Teuhola 2012

  5. JDBC:n mukaanotto sovellusohjelmaan • JDBC-pakkaukset (kuuluvat J2SE:hen):import java.sql.*; // Perus-JDBCimport javax.sql.*; // Laajennuksia, JDBC 2.0, 3.0, 4.0DriverManager pitää kirjaa ajureista, joita samassa sovelluksessa voi olla useita. Ajuri pitää ladata ja rekisteröidä Driver Managerille esim. seuraavasti: Class.forName(“org.postgresql.Driver”)missä ajurin tiedostopolku on em. jar-paketissa. 4-3-OhjRajapinnat Teuhola 2012

  6. Yksinkertaisen JDBC-sovelluksen vaiheet • Ladataan ajuri (vrt. ed.) • Muodostetaan yhteys (Connection) tietokantaan • Luodaan SQL-lause (Statement) • Suoritetaan lause • Käsitellään mahdollinen tulosjoukko (ResultSet), tai siepataan ja käsitellään poikkeukset. • Toistetaan kohtia 3-5 tarpeen mukaan • Suljetaan tietokantaoliot (tulosjoukko, yhteys) 4-3-OhjRajapinnat Teuhola 2012

  7. Yhteyden muodostus tietokantaan • Tarvittava metodi löytyy DriverManager-luokasta: DriverManager.getConnection(<url>, <käyttäjä>, <salasana>);missä <url> on muotoa “jdbc:<ajuri>:<datalähde>”, esim. "jdbc:postgresql://kanta.cs.utu.fi:5432/company“ 4-3-OhjRajapinnat Teuhola 2012

  8. SQL-lauseet • Lause-olioita (Statement-rajapinta) tarvitaan edustamaan SQL-lauseita. • Statement-rajapinnassa on mm. metodeita SQL-lauseen suorittamiseksi. • Tärkeä alirajapinta: PreparedStatement:SQL-lause jäsennetään, tarkistetaan ja käännetään vain kerran, mutta suoritetaan ehkä toistuvasti (tehokkaampi). 4-3-OhjRajapinnat Teuhola 2012

  9. Statement-olion luonti ja suoritus • Luonti Connection-olion createStatement-metodilla. • Suoritus executeQuery- tai executeUpdate-metodilla lauseen tyypistä riippuen. Kyselyn tulos on tyyppiä ResultSet. Esimerkki:Connection c = DriverManager.getConnection(url, user, pwd); Statement st = c.createStatement(); ResultSet res = st.executeQuery( "SELECT Ano, Animi FROM Asiakas;"); 4-3-OhjRajapinnat Teuhola 2012

  10. Statement-olion luonti ja suoritus (jatk.) • ResultSet-olio (esimerkissä res) edustaa 2-ulotteista taulukkoa, jota voidaan kulkea iteraattorin tapaan rivi kerrallaan (vrt. SQLJ:n ‘iterator’). • Ensin res osoittaa 1. rivin ‘edelle’, josta res.next()-metodilla saadaan 1., 2., … rivi, kunnes res==NULL. • Yksittäiset rivin alkiot saadaan res.getxxx(sarake)-metodeilla, missä ‘xxx’ on alkion tyyppi (getInt, getLong, getFloat, getDouble, getString, getBoolean, getDate, getTime, getObject, ym.). • ‘Sarake’ voidaan ilmaista joko järjestysnumerolla(1, 2, …) tai tulosattribuutin nimellä. 4-3-OhjRajapinnat Teuhola 2012

  11. Statement-olion luonti ja suoritus (jatk.) • JDBC ei tee eroa 1- ja monirivisten tulos-taulukoiden välillä. Jos tuloksessa tiedetään olevan vain 1 rivi, silmukka voidaan välttää, mutta res.next():llä pitää siirtyä 1. riville. • Poikkeuksista: • JDBC-kutsut voivat nostaa mm. SQLException-poikkeuksia. • Ne voidaan joko käsitellä (try … catch …) tai siirtää kutsujalle. 4-3-OhjRajapinnat Teuhola 2012

  12. JDBC-esimerkki // Etsi annetun paikkakunnan henkilöt relaatiosta// Asiakas (Ano, Animi, Paikka).//import java.io.*;import java.sql.*;class HaeAsiakkaat {publicstaticvoid main(String args[]) throws SQLException, IOException {try { Class.forName (“org.postgresql.Driver”); }catch (ClassNotFoundException cnfe) { System.out.println(“Ajuria ei löydy!”); } // jatkuu seur. sivulla … 4-3-OhjRajapinnat Teuhola 2012

  13. JDBC-esimerkki (jatk.) String tunnus = prompt(“Anna käyttäjätunnus”); // Hoputemetodi String salasana = prompt(“Anna salasana”); Connection conn = DriverManager.getConnection( “jdbc:postgresql://host/tietokanta”, tunnus, salasana); String paikkakunta = prompt(“Anna paikkakunta”); String kys = “SELECT Ano, Animi FROM Asiakas ” + “WHERE Paikka = ‘” + paikkakunta + “’;”; Statement stmt = conn.createStatement(); ResultSet res = stmt.executeQuery(kys);while (res.next()) {int no = res.getInt(1); String nimi = res.getString(2); System.out.println(no + “ “ + nimi); } res.close(); conn.close(); } } 4-3-OhjRajapinnat Teuhola 2012

  14. JDBC: SQL-lauseen toistuva suoritus • Lause kannattaa jäsentää ja optimoida vain kerran ja käyttää ‘käännettyä’ versiota toistuvissa suorituksissa. • PreparedStatement (‘valmisteltu’ lause) on tällainen: • perii Statement-rajapinnan, • luonti Connection-olion prepareStatement()-metodilla, • parametrina SQL-lause. • Mutta: Yleensä eri suorituskerroilla on jotain eroa; SQL-lause on voitava parametrisoida. 4-3-OhjRajapinnat Teuhola 2012

  15. PreparedStatement:SQL-lauseen parametrisointi • JDBC-ratkaisu:SQL-lauseeseen sijoitetaan tuntemattomien osien kohdalle ‘?’-merkkejä, jotka voidaan eri kerroilla sitoa eri parametriarvoihin. • ‘?’-parametrit ajatellaan numeroiduiksi 1, 2, … • Parametrisointi rajoitettua; esim. FROM-osan relaationimiä ei voi parametrisoida. • Parametrien asetus setxxx()-metodeilla (setInt, setFloat, setString, …) 4-3-OhjRajapinnat Teuhola 2012

  16. “Etsi annettujen paikkakuntien asiakkaat” // … Alkuosa kuten edellä. String kys = “SELECT Ano, Animi FROM Asiakas ” + “WHERE Paikka = ?;”; PreparedStatement ps = conn.prepareStatement(kys); String paikka = prompt(“Anna paikkakunta, lopuksi tyhjä”);while (!(paikka.equals(“”))) { System.out.println(“Paikkakunnan ” + paikka + “ asiakkaat”); ps.setString(1, paikka); ResultSet res = ps.executeQuery();while (res.next()) {int no = res.getInt(1); String nimi = res.getString(2); System.out.println(no + “ “ + nimi); } res.close(); paikka = prompt(“Anna paikkakunta, lopuksi tyhjä”); } conn.close(); }} 4-3-OhjRajapinnat Teuhola 2012

  17. JDBC: Päivityslauseet • Metodilla executeQuery() voidaan suorittaa vain SELECT-lauseita. • Päivityslause suoritetaan käskyllä executeUpdate(), joka palauttaa päivitettyjen rivien määrän. 4-3-OhjRajapinnat Teuhola 2012

  18. “Annetun valmistajan tuotteille annetun suuruinen alennus” // Relaatioskeema:// Tuote (Tno, Tnimi, Valmistaja, Hinta) …String valm = prompt(“Anna valmistaja”);int ale = promptInt(“Anna alennusprosentti”);String paiv = “UPDATE Tuote “ + “SET Hinta = Hinta*(100-” + ale + “)/100 “ + “WHERE Valmistaja = ‘“ + valm + “’;”);int lkm = conn.executeUpdate(paiv);System.out.println(lkm + “ tuotetta halpeni”);… 4-3-OhjRajapinnat Teuhola 2012

  19. Yleistetty ResultSet-rajapinta • Mahdollistaa monipuolisemman vierityksen (scroll): first(), last(), next(), previous(), absolute(int), relative(int) • Mahdollistaa nykyistä ResultSet-riviä vastaavan tietokantarivin päivityksen. • Vrt. SQLJ:#sql iterator … implements sqlj.runtime.ForUpdate • Yleistetty tulosjoukko määritellään Statement-olion luonnin yhteydessä. 4-3-OhjRajapinnat Teuhola 2012

  20. Yleistetty ResultSet-rajapinta (jatk.) • Lauseen luonti esim.Statement lause = conn.createStatement( ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE); • Lauseen suoritus esim.:ResultSet res = lause.executeQuery( "SELECT Ano, Animi, Paikka FROM Asiakas;"); • Päivitys, esim. kolmanteen tulosriviin uusi paikka:res.absolute(3); // Siirtyminen 3. rivilleres.updateString(“Paikka", “Parainen"); // Uusi arvores.updateRow(); // Päivittää lähderelaation vastinrivin 4-3-OhjRajapinnat Teuhola 2012

  21. Esimerkki ResultSet-päivityksestä // Relaatio: Tuote(Tno, Tnimi, Valmistaja, Hinta) // Laske ‘Vipu Oy:n’ tuotteiden hintoja 5 €:lla. // public static void laskeHintoja(Connection conn) throws Exception { String kys = "SELECT * FROM Tuote WHERE Valmistaja='Vipu Oy‘;"; Statement lause = conn.createStatement( ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet res = lause.executeQuery(kys); while (res.next()) { res.updateInt("hinta", res.getInt("hinta") - 5); res.updateRow(); } res.close(); conn.commit(); conn.close(); } 4-3-OhjRajapinnat Teuhola 2012

  22. Ehtoja ResultSet-päivitykselle • Tulosrivien alkuperä tietokannassa pitää pystyä automaattisesti ja yksikäsitteisesti selvittämään • Päivitys mahdollinen, jos • Tulosjoukko on peräisin yhdestä relaatiosta (ei esim. liitoksia) • Relaation pääavain on mukana tulosattribuuteissa. • Huom! Kyseessä on täsmälleen sama ongelma kuin näkymän (view) päivityksessä.Resultset on itse asiassa eräs näkymä kantaan 4-3-OhjRajapinnat Teuhola 2012

  23. JDBC: Mielivaltaiset lauseet • Jos lauseesta ei etukäteen tiedetä, onko se kysely vai päivitys (esim. käyttäjä on syöttänyt sen suorituksen aikana), käytetään execute()-metodia, joka palauttaa boolean-arvon true, jos lause oli kysely, muuten false. Tuloksen poiminta tehdään eri tavoilla tästä riippuen. 4-3-OhjRajapinnat Teuhola 2012

  24. Esimerkki: SQL-lauseen lukeminen näppäimistöltä ja suoritus …String lause = prompt(“Anna SQL-lause”);Statement st = conn.createStatement();boolean tulos = st.execute(lause);if (tulos) { ResultSet rs = st.getResultSet(); …}else {int lkm = st.getUpdateCount(); …}… 4-3-OhjRajapinnat Teuhola 2012

  25. Kyselyn tulokseen liittyvä metadata • Tarvitaan, jos metadata (eli skeemaan liittyvä data) ei ole tiedossa ohjelmaa kirjoitettaessa (vrt. ed. sivun esimerkki).…ResultSet rs = st.getResultSet();ResultSetMetaData rsmd = rs.getMetaData();int sarLkm = rsmd.getColumnCount();for (int sar = 1; sar <= sarLkm; sar++) { System.out.println(“Sarake no “ + sar); System.out.println(“Nimi: “+ rsmd.getColumnName(sar)); System.out.println(“Tyyppi: “ + rsmd.getColumnTypeName(sar)); …} 4-3-OhjRajapinnat Teuhola 2012

  26. Tietokantayhteyteen liittyvä metadata • Toistasataa erilaista tietoa, esim. tiedot ajurista:…Connection conn = DriverManager.getConnection(…);DatabaseMetaData dbmd = conn.getMetaData();System.out.println(“Ajuri: “ + dbmd.getDriverName());System.out.println(“Versio: “ + dbmd.getDriverVersion());… 4-3-OhjRajapinnat Teuhola 2012

  27. Transaktioiden hallinta • Oletusarvoisesti jokainen lause muodostaa oman transaktionsa. • Eksplisiittinen hallinta (conn tyyppiä Connection): conn.setAutoCommit(false); … …Päivityslauseita … conn.commit(); // tai conn.rollback(); • Voi syntyä SQLException, joka on käsiteltävä. 4-3-OhjRajapinnat Teuhola 2012

  28. Ohjelmointitekniikoista • Java-ohjelmoinnissa luokkien suunnittelu on keskeisessä asemassa. • Tietokannan käyttö kannattaa keskittää omiin luokkiinsa/metodeihinsa, esim. seuraavasti: • Ajuriin liittyvät toiminnot • Tietokantayhteyteen liittyvät toiminnot • Relaatioita edustavat ‘kuoriluokat’ (‘wrapper’) • Relaatioiden rivejä (= tietokannan varsinaisia ‘olioita’) edustavat luokat • Varsinaiset sovellukset 4-3-OhjRajapinnat Teuhola 2012

  29. Esimerkki apuluokasta:Ajurin ja tietokantayhteyden hallinta import java.io.*; import java.sql.*; import java.util.*; public class Yhteys { public static Connection luoYhteys(String kanta) throws Exception { String driver = "org.postgresql.Driver"; String url = "jdbc:postgresql://kanta.cs.utu.fi:5432/" + kanta; String user = “ewert"; BufferedReader in = new BufferedReader(new FileReader("sala.txt")); String pwd = in.readLine(); Class.forName(driver); Connection conn = DriverManager.getConnection(url, user, pwd); return conn; } public static void suljeYhteys(Connection conn) throws Exception { conn.close(); } } 4-3-OhjRajapinnat Teuhola 2012

  30. Esimerkki relaation riviä edustavasta luokasta // Asiakas-entiteetti import java.util.*; public class Asiakas { privateint ano; // Yksityisetprivate String animi; // esiintymä-private String paikka; // muuttujat public Asiakas(int no, int ni, String pa) { Ano = no; animi = ni; paikka = pa; // Alustaja}public int getAno() { return ano; } // Ns.public String getAnimi() { return animi; } // getter-public String getPaikka() { return paikka; } // metoditpublic String toString() {return getAno()+”, ’”+getAnimi()+’”, ”’+getPaikka()+”’”; } 4-3-OhjRajapinnat Teuhola 2012

  31. Esimerkki relaation ‘kuoriluokasta’ // Asiakas(Ano, Animi, Paikka)-relaatiota edustava luokka import java.util.*; import java.sql.*; public class Asiakkaat { // Uuden asiakkaan lisäys; yhteys oltava luotu public static void uusiAsiakas(Connection conn, Asiakas a) { try { Statement st = conn.createStatement(); String lause = "INSERTINTO Asiakas VALUES(" + a.toString() + “)”; int riveja = st.executeUpdate(lause); conn.commit(); } catch (SQLException se) { System.out.println("Lisäys pieleen!“ + se.toString()); } } 4-3-OhjRajapinnat Teuhola 2012

  32. Esimerkki relaation ‘kuoriluokasta’ (jatk.) // Paikkakunnan asiakkaiden haku Asiakas-relaatiosta (vrt. aik. esim.)// public static ArrayList<Asiakas> haeAs(Connection conn, String pnimi) { ArrayList<Asiakas> arr = new ArrayList<Asiakas>(); try { Statement st = conn.createStatement(); String lause = “SELECT Ano, Animi, Paikka “ + “FROM Asiakas WHERE Paikka =‘”+pnimi + “‘;”; ResultSet res = st.executeQuery(lause); while (res.next()) { Asiakas a = new Asiakas( res.getInt(“Ano”), res.getString(“Animi”), res.getString(“Paikka”)) arr.add(a); } res.close(); } catch (SQLException se) { System.out.println("Paikanhaku ei onnistunut!“ + se.toString()); } return arr; } 4-3-OhjRajapinnat Teuhola 2012

  33. Esimerkki relaation ‘kuoriluokasta’ (jatk.) // Asiakkaan paikkakunnan muutos publicstaticvoid muutaPaikka( Connection conn, Asiakas a, String uusiPaikka) { try { conn.setAutoCommit(false); // Transaktio hallitaan itse Statement st = conn.createStatement(); String lause = “UPDATE Asiakas “ + “SET Paikka=‘” + uusiPaikka + “‘” + “WHERE Ano=" + a.getAno() + “;”; int riveja = st.executeUpdate(lause); conn.commit(); // Muutoksen vahvistus } catch (SQLException se) { System.out.println("Paikanmuutos epäonnistui:“+se.toString()); try { conn.rollback(); } catch (SQLException re) { // Peruutus System.out.println(“Rollback meni pieleen: “+ re.toString()); } }} 4-3-OhjRajapinnat Teuhola 2012

  34. Esimerkki relaation ‘kuoriluokasta’ (jatk.) // Koko asiakastaulun tulostus ruudulle public static void tulostaKaikki(Connection conn) { try { Statement st = conn.createStatement(); String lause = "SELECT * FROM Asiakas;"; ResultSet res = st.executeQuery(lause); System.out.println(""); System.out.println(" Ano | Animi | Paikka"); System.out.println("-----------------------"); while (res.next()) { System.out.print(res.getInt(1)); System.out.print(" | "); System.out.print(res.getString(2)); System.out.print(" | "); System.out.println(res.getString(3)); } res.close(); } catch (SQLException se) { System.out.println( "Asiakkaiden haku ei onnistunut!“ + se.toString()); } } 4-3-OhjRajapinnat Teuhola 2012

  35. Esimerkki kuoriluokan testiohjelmasta public static void main( String args[ ] ) throws Exception { Connection conn = Yhteys.luoYhteys("til"); // Alustus Asiakkaat.tulostaKaikki(conn); // Rel. sisältö alussa Asiakas a = new Asiakas(444, "Laine", "Naantali”); Asiakkaat.uusiAsiakas(conn, a); // Uuden lisäys Asiakkaat.tulostaKaikki(conn); // Uusi sisältö ArrayList<Asiakas> arr = Asiakkaat.haePaikka(conn, "Turku"); // Kysely System.out.println("Turkulaiset asiakkaat: "); // Vastaus for (int i=0; i<arr.size(); i++) { System.out.println(arr.get(i).toString()); } // Turkulaiset Asiakkaat.muutaPaikka(conn, a, "Raisio"); // Paikkakunnan vaihto Asiakkaat.tulostaKaikki(conn); // Muutettu sisältö Yhteys.suljeYhteys(conn); // Lopetus } 4-3-OhjRajapinnat Teuhola 2012

  36. Tietokantasovelluksen laatimisesta • Voidaan käyttää erilaisia ohjelmistoratkaisuja, eli ns. suunnittelumalleja. • Yleinen periaate: tietokantaa käsittelevien toimintojen eristäminen omiin luokkiinsa, jolloin niiden ylläpito selkeytyy. • Esim. Data Access Objects (DAO) –malli:Kerrosmainen arkkitehtuuri: • Käyttöliittymä • Sovelluslogiikka • Tietokantaa käsittelevät osat sovelluksesta • JDBC-rajapinta • Tietokanta 4-3-OhjRajapinnat Teuhola 2012

  37. Tietokantaa käsittelevien luokkien rakenteellisia vaihtoehtoja • Muodostetaan yksi (iso) luokka, johon kerätään kaikki tietokantaa käsittelevät metodit. • Muodostetaan yksi luokka kutakin tietokannan entiteettikokoelmaa (eli relaatiota) kohti, johon kootaan ko. relaatioon liittyvät metodit, mutta mahdollisesti myös esim. liitosoperaatiot muiden relaatioiden kanssa. • Muodostetaan yksi luokka kutakin entiteettityyppiä kohti, jonka instanssit vastaavat relaation yksittäisiä rivejä. Yllä tilaus-asiakas-sovelluksessa käytettiin lähinnä kakkosvaihtoehtoa (luokka ’Asiakkaat’). Harjoitustyön malliesimerkissä on piirteitä 1- ja 3-vaihtoehdoista. 4-3-OhjRajapinnat Teuhola 2012

  38. Object-relational mapping (ORM) • Relaatiokannan sovellusohjelmointi sisältää runsaasti saman kaavan mukaisia metodeja, jotka muuntavat Javan olioesityksen relaatiomallin mukaiseksi taulukkoesitykseksi ja päinvastoin. • Muunnos on mahdollista osittain automatisoida, mikä nopeuttaa sovelluskehitystä ja ylläpitoa. • Tarvitaan muunnoksen kuvaus loogisella tasolla.Tämä tehdään usein erillisenä kuvaustiedostona(tyypillisesti XML-kielellä). • Ei poista tietokannan suunnittelutarvetta. • Esimerkki ORM-tuotteesta: Hibernate 4-3-OhjRajapinnat Teuhola 2012

More Related