Tecnologie Web T Accesso Diretto alle Basi di Dati: Interfacce e Astrazioni Home Page del corso: http://www-db.disi.unibo.it/courses/TW/ Versione elettronica: 4.01.AccessoDB.pdf Versione elettronica: 4.01.AccessoDB-2p.pdf Accesso DB 1 … un piccolo passo indietro Modello frequente in applicazioni enterprise Presentation Livello di presentazione si occupa della visualizzazione dei risultati generati secondo il percorso definito nel flusso sottostante Business Flows A questo livello vengono implementati i flussi delle diverse conversazioni che interagiscono per comporre una applicazione Business Logic Services La logica di business contiene le caratteristiche delle applicazioni e dipende sia dal modello dei dati che, ancora più rilevante, dalle logiche di utilizzo degli stessi I servizi devono fornire tutte le funzionalità base (API) necessarie per l’implementazione rapida ed efficace della logica di business, dalla gestione della concorrenza al supporto alle transazioni, dall’interfacciamento ai DB al monitoraggio/controllo/gestione delle performance Accesso DB 2 1 Gestione della persistenza Una parte rilevante degli sforzi nello sviluppo di ogni applicazione distribuita di livello enterprise si concentra sul layer di persistenza Accesso, manipolazione e gestione di dati persistenti, tipicamente mantenuti in un DB relazionale Il mapping Object/Relational si occupa di risolvere il potenziale mismatch fra dati mantenuti in un DB relazionale (table-driven) e il loro processamento fatto da oggetti in esecuzione DB relazionali sono progettati per operazioni di query efficienti su dati di tipo tabellare Necessità di lavorare invece tramite interazione fra oggetti Accesso DB 3 … ancora un piccolo passo indietro Come accedere ai dati di un DB? Dal Corso di Sistemi Informativi T, sappiamo che è possibile mediante istruzioni SQL eseguite “interattivamente” Accesso DB 4 2 Accesso diretto alle basi di dati (1/2) È anche possibile (ed è di gran lunga l’accesso a DB più tipico) inserire istruzioni SQL direttamente nel codice di un’applicazione scritta in un linguaggio di programmazione “ospite” (ad es. C, C++, Java, C#) Esempio Java - JDBC: System.out.println("Retrieve some data from the database.."); Statement stmt = con.createStatement(); ResultSet rs = stmt.executeQuery("SELECT * FROM EMPLOYEE"); // display the result set while (rs.next()) { String number = rs.getString(1); String name = rs.getString(2); System.out.print(" empno= " + number); System.out.print(" firstname= " + name); System.out.print("\n"); } rs.close(); stmt.close(); Accesso DB 5 Accesso diretto alle basi di dati (2/2) Il problema da risolvere è relativo all’integrazione tra i comandi SQL, i quali sono responsabili di realizzare l’accesso al DB, e le normali istruzioni del linguaggio di programmazione Due soluzioni possibili: SQL Embedded o “incastonamento”: SQL viene integrato direttamente all’interno del normale linguaggio di programmazione Es. di soluzione sono i cursori e SQL dinamico Call Level Interface (CLI): l’integrazione con SQL avviene tramite l’invocazione di una opportuna libreria di funzioni Es. di soluzione sono ODBC, OLE DB, ADO e JDBC Accesso DB 6 3 SQL Embedded L’incastonamento prevede di introdurre direttamente nel programma sorgente le istruzioni SQL distinguendole dalle normali istruzioni tramite un opportuno separatore Lo standard SQL prevede che il codice SQL sia preceduto dalla stringa exec sql e termini con il carattere ';’ Preprocessore che espande i comandi SQL Cursori: strumento che permette a un programma di accedere alle righe di una tabella una alla volta; viene definito su una generica interrogazione SQL dinamico: permette all’applicazione di definire al momento dell’esecuzione le interrogazioni SQL da effettuare sulla base di dati Valore dei parametri (per istruzioni con struttura predefinita) Forma delle interrogazioni Accesso DB 7 Call Level Interface Mette direttamente a disposizione del programmatore una libreria di funzioni che permettono di interagire con un DBMS Rispetto a SQL Embedded, CLI rappresenta uno strumento più flessibile e meglio integrato con il linguaggio di programmazione anche se occorre gestire esplicitamente aspetti che con SQL Embedded sono demandati direttamente al preprocessore Accesso DB 8 4 Modo d’uso generale CLI Una applicazione che accede (in lettura e/o scrittura) ad una sorgente di dati ha bisogno di fare le seguenti operazioni: 1. 2. 3. aprire una connessione alla sorgente dati inviare attraverso la connessione istruzioni (di interrogazione e aggiornamento) alla sorgente dati processare i risultati ricevuti dalla sorgente dati in risposta alle istruzioni inviate Le nostre sorgenti dati sono DB relazionali, gestiti da un DBMS a scelta tra DB2 (consigliato), MySQL, Hsqldb Ogni DBMS espone una API (Application Program Interface) Le applicazioni, per noi Java, interagiscono con le API del DBMS attraverso un driver Accesso DB 9 Soluzioni CLI Piattaforma software Microsoft ODBC (Object DataBase Connectivity ): interfaccia standard che permette di accedere a DB in qualunque contesto, realizzando interoperabilità con diverse combinazioni DBMS-Piattaforma-Reti OLE DB (Object Linking and Embedding for DataBases): soluzione proprietaria Microsoft che permette ad applicazioni Windows di accedere a sorgenti dati generiche, non solo relazionali ma anche a una vasta tipologia di archivi dati, quali caselle di posta elettronica; basata sul modello a oggetti COM ADO (ActiveX Data Object): interfaccia proprietaria Microsoft di alto livello ai sevizi offerti da OLE DB basata su una interfaccia “record(tupla)-oriented” JDBC Soluzione per l’accesso ai dati in Java sviluppata da Sun Microsystem; controparte di ODBC per Java Accesso DB 10 5 Diverse soluzioni a confronto Nome Descrizione Pro :) Contro :( SQL Embedded Le istruzione SQL sono introdotte direttamente all’interno del listato programma, distinte da un separatore (exec sql <istruzione> ;) Cursori per gestire risultati composti da più tuple; SQL dinamico per ottenere flessibilità Necessità di un preprocessore e di un supporto “DBMS-piattaformalinguaggio-compilatore” OLE DB/ ADO Soluzione proprietaria Microsoft che consente, grazie all’uso di driver specifici, di interfacciare il linguaggio di programmazione con il DBMS Integrato in Windows; Driver offerti dai maggiori produttori di DBMS; Interfacciamento con altri tipi di dato (documenti, mailbox, ecc.) Dialetto SQL ristretto; Proprietario; Utilizzato solo su linguaggi e su piattaforme Microsoft JDBC Interfaccia fra il mondo Java ed i diversi DBMS. Utilizza dei driver specifici ma offre anche un ponte con ODBC (non è vero l’inverso) Java, multipiattaforma, codice aperto; Disponibile per qualsiasi DBMS grazie anche al ponte ODBC Come ODBC richiede la disponibilità di un driver offerto dal DBMS Accesso DB 11 ODBC Acronimo di Open Database Connectivity API standard definita da Microsoft nel 1992 Permette l’accesso a dati residenti in DB relazionali in un contesto eterogeneo e distribuito Es. DBMS: Access, MySQL, DB2, Oracle, Hsqldb, … Permette ai programmatori di formulare richieste SQL che accederanno a dati relativi a DB distinti senza dover conoscere le interfacce proprietarie di ogni singolo DB Gestisce richieste SQL convertendole in un formato comprensibile al particolare DBMS Accesso DB 12 6 Architettura ODBC Application ODBC Driver Manager ODBC Driver (DBMS/OS/network) Data Source Accesso DB 13 JDBC API Java standard definita da Sun Microsystems nel 1996 Sun assicura che JDBC NON è acronimo di Java Database Connectivity… ma è un semplice marchio registrato!! ☺ Rappresenta la controparte Java di ODBC Permette di accedere ai database (locali e remoti) in modo uniforme Garantisce accesso ai database in modo indipendente dalla piattaforma I driver JDBC sono collezioni di classi Java che implementano metodi definiti dalle specifiche JDBC Le classi Java che realizzano funzionalità JDBC sono contenute nei package java.sql: classi fondamentali javax.sql: estensioni Accesso DB 14 7 JDBC vs ODBC ODBC non è appropriato per un uso diretto dal linguaggio Java perché usa interfacce scritte in linguaggio C Una traduzione da API ‘C’ ODBC a API ‘Java’ non è raccomandata Una API Java come JDBC è necessaria per permettere una soluzione Java “pura” JDBC è normalmente utilizzato da programmatori Java per connettersi a DB relazionali Attraverso un piccolo programma “bridge” è possibile usare l’interfaccia JDBC per accedere a DB accessibili via ODBC Accesso DB 15 Storia di JDBC Prima distribuzione (jdbc.sql) JDBC fa parte del pacchetto software JDK a partire dalla versione 1.1 (pakage java.sql) Con Java 2, è stato introdotto JDBC 2.0: Migliorate le funzionalità e i tipi di dato disponibili Offerto come package opzionale per funzionalità estese Java SE 8 include JDBC 4.2 Accesso DB 16 8 Architettura JDBC Java Application utilizza le interfacce java.sql e javax.sql JDBC Driver Manager Type 2 Type 1 JDBC/Native Bridge JDBC/ODBC Bridge Native Driver (DBMS specific) ODBC Driver Type 4 All Java JDBC Driver Type 3 implementano java.sql e, in alcuni casi javax.sql All Java JDBC/Net Bridge Network Server DBMS data source Accesso DB 17 JDBC Driver Manager Rappresenta il livello di gestione di JDBC e opera tra l’utente e i driver Tiene traccia dei driver disponibili e gestisce la creazione di una connessione tra un DB e il driver appropriato Accesso DB 18 9 Driver JDBC JDBC è un insieme di interfacce; per usare un’interfaccia è necessario fornire un’implementazione per tutti i metodi che la compongono L’insieme delle classi Java che implementano le interfacce JDBC rappresentano un modulo software chiamato driver JDBC Ogni DBMS ha il proprio driver rilasciato dal produttore o sviluppato da terze parti Sono i driver che realizzano la vera comunicazione con il DB Accesso DB 19 Tipi di driver (1/3) Sono di quattro tipi e possono essere suddivisi in due categorie: 2-tier: client colloquiano direttamente con DB 3-tier: client comunicano con un middle-tier che accede al DB Accesso DB 20 10 Tipi di driver (2/3) Modello 3-tier: affinché l’applicazione possa interagire con il DB occorre che le chiamate JDBC siano convertite in chiamate API native (caso JDBC/native bridge) o in chiamate ODBC (caso JDBC/ODBC bridge) L’utente può utilizzare una API di alto livello (di più semplice utilizzo) che viene tradotta dal driver in chiamate di basso livello Non è realmente portabile in quanto richiede l’utilizzo di componenti nativi (specifici dell’ambiente in cui vengono eseguiti) Modello 2-tier: l’applicazione interagisce direttamente con il DB mediante un opportuno protocollo di rete, per es. TCP/IP (caso driver JDBC middleware, detto anche NetDriver), oppure mediante un protocollo di rete proprietario (caso driver JDBC Driver) Si appoggia su un ambiente completamente Java Accesso DB 21 Tipi di Driver (3/3) Type 1 - drivers that implement the JDBC API as a mapping to another data access API, such as ODBC. Drivers of this type are generally dependent on a native library, which limits their portability (JDBCODBC Bridge driver is an example of a Type 1 driver) Type 2 - drivers that are written partly in the Java programming language and partly in native code. These drivers use a native client library specific to the data source to which they connect. Again, because of the native code, their portability is limited Type 3 - drivers that use a pure Java client and communicate with a middleware server using a database-independent protocol. The middleware server then communicates the client’s requests to the data source Type 4 - drivers that are pure Java and implement the network protocol for a specific data source. The client connects directly to the data source Accesso DB 22 11 Driver: Type 1, Type 2 Type 1: JDBC-ODBC Bridge plus ODBC Driver This combination provides JDBC access via ODBC drivers. ODBC binary code -and in many cases, database client code -- must be loaded on each client machine that uses a JDBC-ODBC Bridge. Sun provides a JDBC-ODBC Bridge driver, which is appropriate for experimental use and for situations in which no other driver is available Type 2 : A native API partly Java technology-enabled driver This type of driver converts JDBC calls into calls on the client API for Oracle, Sybase, Informix, DB2, or other DBMS. Note that, like the bridge driver, this style of driver requires that some binary code be loaded on each client machine Accesso DB 23 Driver: Type 3, Type 4 Type 4: Direct-to-Database Pure Java Driver This style of driver converts JDBC calls into the network protocol used directly by DBMSs, allowing a direct call from the client machine to the DBMS server and providing a practical solution for intranet access Type 3: Pure Java Driver for Database Middleware This style of driver translates JDBC calls into the middleware vendor's protocol, which is then translated to a DBMS protocol by a middleware server. The middleware provides connectivity to many different databases Accesso DB 24 12 Tipi di driver a confronto Tipo 1: Ponte JDBC-ODBC Driver prestazioni scadenti non indipendente dalla piattaforma fornito a corredo di JDK Tipo 2: Ponte JDBC-Native Driver migliori prestazioni non indipendente dalla piattaforma Tipo 3: Driver Java Puro per Accesso a DB via Middleware client indipendente dalla piattaforma servizi avanzati (caching) architettura complessa Tipo 4: Driver Java Puro per Accesso Diretto a DB client indipendente dalla piattaforma buone prestazioni scaricabile dinamicamente Per approfondimenti: http://java.sun.com/products/jdbc/driverdesc.html Accesso DB 25 Schema di uso di JDBC Accesso a DB con JDBC consiste nel: Caricare la classe del driver JDBC Ottenere una connessione dal driver Eseguire statement SQL Utilizzare risultati delle query Chiudere la connessione e rilasciare strutture dati utilizzate per la gestione del dialogo con il DB Class.forName(“com.ibm.db2.jcc.DB2Driver").newInstance(); Connection conn = DriverManager.getConnection("jdbc:db2:MYDB"); Statement stm = conn.createStatement(); ResultSet res = stm.executeQuery("SELECT * FROM MYTABLE"); while (res.next()) { String col1 = res.getString("MYCOL1"); int col2 = res.getInt("MYCOL2"); } Accesso DB 26 13 Interfacce e calssi JDBC L’API JDBC 4.0 core mette a disposizione più di 20 tra interfacce e classi Alcune fra le più importanti sono Driver DriverManager Connection Statement ResultSet Accesso DB 27 Interfaccia Driver (1/2) Rappresenta il punto di partenza per ottenere una connessione a un DBMS I produttori di driver JDBC implementano l’interfaccia Driver (mediante opportuna classe) affinché possa funzionare con un tipo particolare di DBMS La classe che implementa Driver può essere considerata la “factory” per altri oggetti JDBC ad esempio, oggetti di tipo Connection Ad esempio, IBM nel suo Driver Java “Puro” implementa l’interfaccia Driver mediante la classe: com.ibm.db2.jcc.DB2Driver Accesso DB 28 14 Interfaccia Driver (2/2) È possibile ottenere un’istanza effettiva della classe Driver ricercando la classe con il metodo forName: Driver d = Class.forName(“com.ibm.db2.jcc.DB2Driver”). .newInstance(); Avendo a disposizione un oggetto Driver è possibile ottenere la connessione al database Ogni driver JDBC ha una stringa di connessione che riconosce nella forma: jdbc:product_name:database_alias dove database_alias specifica il DB a cui connettersi nel caso specifico della configurazione DB2 in LAB4: jdbc:db2://diva.deis.unibo.it:50000/[sample|tw_stud] Accesso DB 29 Classe DriverManager Facilita la gestione di oggetti di tipo Driver Quando un oggetto Driver viene istanziato, esso viene automaticamente registrato nella classe DriverManager Ogni applicazione può registrare uno o più driver JDBC diversi tra loro Consente la connessione con il DBMS sottostante Mediante il metodo statico getConnection Usa il driver opportuno tra quelli registrati Accesso DB 30 15 Interfaccia Connection Un oggetto di tipo Connection rappresenta una connessione attiva con il DB Il metodo getConnection di DriverManager, se non fallisce, restituisce un oggetto di tipo Connection L’interfaccia mette a disposizione una serie di metodi per le operazioni, tra le quali: Preparazione di query SQL da inviare tramite oggetti Statement PreparedStatement CallableStatement Accesso DB 31 Interfaccia Statement Gli oggetti di tipo Statement possono essere usati per inviare query SQL semplici verso il DBMS sottostante query che non fanno uso di parametri La query può essere di modifica UPDATE, INSERT, CREATE oppure di selezione SELECT Per query di tipo SELECT il risultato è inserito in un oggetto ResultSet Un oggetto Statement può essere creato con il metodo createStatement di Connection Accesso DB 32 16 Interfaccia PreparedStatement Gli oggetti di tipo PreparedStatement possono essere usati per creare query SQL parametriche (parametri di tipo IN) e precompilate (“prepared”) Il valore di ciascun parametro non è specificato nel momento in cui lo statement SQL è definito, ma rimpiazzato dal carattere ‘?’ È più efficiente perché una volta che la query è preparata, sarà pre-compilata per usi futuri Un oggetto PreparedStatement può essere creato con il metodo prepareStatement di Connection Accesso DB 33 Interfaccia CallableStatement Gli oggetti di tipo CallableStatement possono essere usati per definire query parametriche con parametri di tipo IN, OUT e INOUT Permettono di eseguire una invocazione a una stored procedure memorizzata sul server DB Un oggetto CallableStatement può essere creato con il metodo prepareCall di Connection Accesso DB 34 17 Interfaccia ResultSet L’oggetto ResultSet è il risultato di una query di selezione (SELECT) Rappresenta una tabella composta da righe (gli elementi selezionati) e colonne (gli attributi richiesti) Nella versione 1.x di JDBC era possibile accedere a un ResultSet obbligatoriamente dal primo elemento all’ultimo e una sola volta Da JDBC 4.x si può accedere in modo casuale alle righe, inserirle, cancellarle e modificarle Accesso DB 35 JDBC e DB2 DB2 prevede 2 driver JDBC di tipo two-tier: 1. Net-Driver: com.ibm.db2.jcc.DB2Driver 2. Driver Java “puro”: com.ibm.db2.jcc.DB2Driver entrambi contenuti nel file db2jcc.jar (direttorio C:\Programmi\IBM\SQLLIB\java della macchina client del laboratorio) Il Net-Driver serve per connettersi via rete (ad esempio, mediante il protocollo di rete TCP/IP) a server remoti – è un driver universale, ovvero indipendente dalla piattaforma a condizione che questi abbiano attivo il servizio DB2 Jdbc Applet Server Il Driver Java puro permette di connettersi ad istanze DB2 residenti sulla macchina locale o catalogate localmente Accesso DB 36 18 Programmare un’applicazione JDBC Passi principali: 1. 2. 3. 4. 5. Importazione package Registrazione driver JDBC Apertura connessione al DB (Connection) Creazione oggetto Statement Esecuzione query e eventuale restituzione oggetto ResultSet 6. Utilizzo risultati 7. Chiusura oggetto/i ResultSet e oggetto/i Statement 8. Chiusura connessione Accesso DB 37 1: Importazione package // // // // Questo programma mostra un *semplice esempio* di applicazione Java (Esempio.java) in grado di eseguire interrogazioni/aggiornamenti sul database DB2 “SAMPLE” utilizzando JDBC //importazione package import java.sql.*; //package JDBC Accesso DB 38 19 2: Registrazione driver JDBC class Esempio { public static void main(String argv[]) { try { // caricamento e registrazione driver Class.forName(“com.ibm.db2.jcc.DB2Driver").newInstance(); … Accesso DB 39 3: Apertura connessione DB Connection con = null; // URL jdbc:db2:database_alias String url = "jdbc:db2://diva.deis.unibo.it:50000/sample"; if (argv.length == 2) { String userid = argv[0]; String passwd = argv[1]; // connessione con id/passwd forniti dall’utente con = DriverManager.getConnection(url, userid, passwd); } else { System.out.println("\nUsage: java Esempio username password\n"); System.exit(0); } … Accesso DB 40 20 4. Creazione oggetto Statement // interrogazione table EMPLOYEE System.out.println("Retrieve some data from the database"); Statement stmt = con.createStatement(); … Accesso DB 41 5. Esecuzione query 6. Utilizzo oggetto ResultSet // esegue la query ResultSet rs = stmt.executeQuery("SELECT * FROM DB2INST1.EMPLOYEE"); System.out.println("Received results:"); // mostra i risultati // rs.next() = “false” se non ci sono più righe risultato while (rs.next()) { String number = rs.getString(1); String name = rs.getString(2); System.out.print(" empno= " + number); System.out.print(" firstname= " + name); System.out.print("\n"); } … Accesso DB 42 21 7. Chiusura oggetti ResultSet e Statement // chiude ResultSet e Statement rs.close(); stmt.close(); // Esecuzione di altre istruzioni SQL // aggiorna il database… prova ad aggiornarlo! ☺ System.out.println("\n\nUpdate the database... "); stmt = con.createStatement(); int rowsUpdated = stmt.executeUpdate("UPDATE DB2INST1.EMPLOYEE SET firstname = 'SHILI’ WHERE empno = '000010'"); System.out.print("Changed "+rowsUpdated); if (1 == rowsUpdated) System.out.println(" row."); else System.out.println(" rows."); stmt.close(); // chiude Statement … Accesso DB 43 8. Chiusura connessione // chiude Connection con.close(); } // try catch( Exception e ) { e.printStackTrace(); } } // main } // classe Scopo di questo semplice esempio didattico è solo quello di evidenziare l’uso di base delle API JDBC Come vedremo meglio in laboratorio connessione, statement, resultSet devono essere sempre “chiusi” dopo essere stati usati (rilasciamo risorse!!) Per aver questa garanzia, effettuiamo queste operazioni sempre nella clausola finally Ogni metodo JDBC “lancia” una eccezione; tali eccezioni possono essere gestite rilanciando una eccezione di livello logico opportuno Accesso DB 44 22 Oggetto Statement Un oggetto Statement fornisce tre metodi per eseguire una query SQL: (StatementObj.) executeQuery(stmt SQL), per statement che generano un unico result set (SELECT) (StatementObj.) executeUpdate(stmt SQL), per statement di modifica (UPDATE, INSERT, ecc.) (StatementObj.) execute(stmt SQL), per statement che generano più di un risultato o più di un contatore di aggiornamento Accesso DB 45 executeQuery Usato tipicamente per query di tipo SELECT Restituisce un oggetto ResultSet Accesso DB 46 23 executeUpdate Usato per statement di tipo DML quali INSERT, UPDATE o DELETE e per statement di tipo DDL quali CREATE TABLE e DROP TABLE Restituisce un intero rappresentante il numero di righe che sono state inserite/aggiornate/cancellate contatore di aggiornamento In caso di statement di tipo DDL, restituisce sempre il valore 0 Accesso DB 47 execute Usato quando la query restituisce più di un risultato o più di un contatore di aggiornamento Utilizza i seguenti metodi: (StatementObj.) getResultSet() per ottenere il result set successivo (StatementObj.) getUpdateCount() per ottenere il contatore di aggiornamento successivo (StatementObj.) getMoreResults() per sapere se ci sono altri result set o contatori di aggiornamento Restituisce true se il primo risultato è di tipo ResultSet; false se il risultato è di tipo Count o non ci sono più risultati Accesso DB 48 24 Oggetto ResultSet Un oggetto ResultSet contiene il risultato di una query SQL (cioè una tabella) Un oggetto ResultSet mantiene un cursore alla riga corrente Per ottenere un valore relativo alla riga corrente: (ResultSetObj.) getXXX(column-name) (ResultSetObj.) getXXX(column-number) Per spostare il cursore dalla riga corrente a quella successiva: (ResultSetObj.) next() (restituisce true in caso di successo; false se non ci sono più righe nell’insieme risultato) 49 Accesso DB I metodi getxxx Permettono la lettura degli attributi di una tabella getByte getShort getInt getLong getFloat getDouble getBigDecimal getBoolean Accesso DB getString getBytes getDate getTime getTimestamp getAsciiStream getUnicodeStream getBinaryStream getObject 50 25 Controllo sui valori NULL I valori NULL SQL sono convertiti in null, 0, o false, dipendentemente dal tipo di metodo getXXX Per determinare se un particolare valore di un risultato corrisponde a NULL in JDBC: Si legge la colonna Si usa il metodo (ResultSetObject.) wasNull() Accesso DB 51 Controllo sui tipi di dato Il dialogo tra una applicazione Java e i DB sottostanti richiede che i tipi di dato SQL siano mappati in corrispondenti tipi di dato Java e viceversa. La conversione (SQL2Java) riguarda tre categorie: Tipi SQL che hanno diretti equivalenti in Java (es. il tipo SQL INTEGER è equivalente al tipo Java int) Tipi SQL che possono essere convertiti negli equivalenti tipi Java (es. i tipi SQL CHAR e VARCHAR possono essere convertiti nel tipo Java String) Tipi SQL che sono unici (una minoranza) e che necessitano la creazione di uno speciale oggetto Java (es. il tipo SQL DATE si converte nell’oggetto Date definito dall’omonima classe Java) Accesso DB 52 26 Mapping SQL2Java SQL type Java Type SQL Type Java Type CHAR String BIGINT long VARCHAR String REAL float LONGVAR CHAR String FLOAT double DOUBLE double NUMERIC java.math.Big Decimal BINARY byte[] VARBINARY byte[] DECIMAL java.math.Big Decimal LONGVAR BINARY byte[] BIT boolean DATE java.sql.Date TINYINT byte TIME java.sql.Time SMALLINT short INTEGER int TIMESTAMP java.sql.Time stamp Accesso DB 53 Oggetto PreparedStatement Usato quando la query SQL prende uno o più parametri come input, o quando una query semplice deve essere eseguita più volte L’interfaccia PreparedStatement estende l’interfaccia Statement ereditandone tutte le funzionalità. In più sono presenti metodi per la gestione dei parametri L’oggetto viene creato con l’istruzione Connection.prepareStatement(stmt SQL) I parametri vengono poi settati mediante il metodo (StatementObj.) setXXX(n,value) La query pre-compilata viene eseguita mediante i metodi executeQuery(), executeUpdate()o execute() senza bisogno di passare alcun parametro!! Accesso DB 54 27 PreparedStatement: Esempio I parametri sono specificati con “?” Esempio: PreparedStatement ps = con.prepareStatement( "UPDATE MyTable SET a = ? WHERE b = ?"); Per istanziare i parametri “?” (necessariamente prima dell’esecuzione): ps.setInt(1, 20); ps.setInt(2,100); Per eseguire lo statement: int res = ps.executeUpdate(); 55 Accesso DB I metodi setxxx Permettono l’assegnamento dei parametri di uno statement SQL setByte setShort setInt setLong setFloat setDouble setBigDecimal setBoolean setNull Accesso DB setString setBytes setDate setTime setTimestamp setAsciiStream setUnicodeStream setBinaryStream setObject 56 28 Mapping Java2SQL Java Type SQL type String VARCHAR or LONGVARCHAR Java Type SQL type float REAL double DOUBLE java.math. BigDecimal NUMERIC byte[] VARBINARY or LONGVARBINARY boolean BIT java.sql.Date DATE byte TINYINT short SMALLINT java.sql.Time TIME int INTEGER long BIGINT java.sql.Timestamp TIMESTAMP Accesso DB 57 Il problema dell’SQL injection Cosa succede se, data una query con valori di input dell’utente (es. tramite interfaccia Web), questi ha la possibilità di agire direttamente sul valore dell’input di tipo stringa (oggetto String), aggiungendo, ad esempio, apici e altre istruzioni di controllo?? Può inserire istruzioni arbitrarie che verranno eseguite dal DBMS!!! Esempio: Statement = “SELECT * FROM users WHERE name = ‘“ + userName + ”’;” con la variabile userName assegnata al valore: a’;DROP TABLES users; Accesso DB 58 29 SQL injection È una tecnica che sfrutta la vulnerabilità a livello di sicurezza dello strato DB di una applicazione Tale vulnerabilità è presente quando i dati di input dell’utente sono: Filtrati in modo incorretto per la verifica di caratteri literal escape nelle stringhe Non sono fortemente “tipati” o non sono controllati i vincoli di tipo SQL injection in quanto l'utente può “iniettare” statement SQL arbitrari con risultati catastrofici: divulgazione di dati sensibili o esecuzione di codice Per proteggere le nostre applicazioni dall’SQL injection, i dati di input dell’utente NON devono essere direttamente incastonati all’interno di Statement SQL Accesso DB 59 Prevenire SQL injection A prevenzione del problema, l’interfaccia PreparedStatement permette di gestire in modo corretto anche l’inserimenti di dati “ostili” Si tratta di statement “parametrizzati” che permettono di lavorare con parametri (o variabili bind) invece che di incastonare i dati di input dell’utente direttamente nello statement SQL statement è fisso i dati di input dell’utente sono assegnati ai parametri (bounding) Accesso DB 60 30 La storia del piccolo “Bobby Tables” (From the comic strip xkcd) School: "Hi, this is your son's school. We're having some computer trouble." Mom: "Oh, dear -- Did he break something?" School: "In a way. Did you really name your son Robert'); DROP TABLE Students;-- ?" Mom: "Oh. Yes. Little Bobby Tables we call him." School: "Well, we've lost this year's student records. I hope you're happy." Mom: "And I hope you've learned to sanitize your database inputs." (Alt-text: "Her daughter is named Help I'm trapped in a driver's license factory.") C’è solo un modo per evitare attacchi di tipo Bobby Tables Non creare mai statement SQL che includono dati di input utente Usare sempre chiamate SQL parametrizzate (PreparedStatement) Accesso DB 61 Riferimenti Sito Sun - The Java Tutorial http://java.sun.com/docs/books/tutorial/jdbc /index.html Sito Sun – Java SE - Java Database Connectivity (JDBC) http://java.sun.com/javase/technologies/data base/index.jsp Per la documentazione relativa ai pakage java.sql e javax.sql, fare riferimento a Java2Docs Atzeni, Ceri, Paraboschi, Torlone. “Basi di dati: Modelli e linguaggi di interrogazione”, McGraw-Hill Italia, 2009 Accesso DB 62 31