Java & PostgreSQL: da JDBC a Pl/Java (passando per org.postgresql.driver)

Dimensione: px
Iniziare la visualizzazioe della pagina:

Download "Java & PostgreSQL: da JDBC a Pl/Java (passando per org.postgresql.driver)"

Transcript

1 Java & PostgreSQL: da JDBC a Pl/Java (passando per org.postgresql.driver) Ing. Luca Ferrari, PhD Italian PostgreSQL Users Group ITPug

2 Synopsis Questa presentazione vuole fungere da punto di riferimento per gli sviluppatori Java che vogliano scrivere applicazioni capaci di gestire i dati contenuti in un cluster PostgreSQL. In questa presentazione verranno mostrate le principali tecniche per la connettività Java verso PostgreSQL (tramite JDBC), il funzionamento interno del driver JDBC ufficiale nonché come estendere il database PostgreSQL con tecnologia Java tramite Pl/Java. Gli esempi di applicazioni/database qui riportati sono a puro scopo didattico. 2 di 182

3 Database didattico CREATE TABLE corso ( corsopk serial NOT NULL, Chiave surrogata della tabella corso. corsoid character varying(10), Chiave reale della tabella corso. descrizione text, Descrizione del corso requisiti text, Elenco dei requisiti richiesti data date, Data in cui si tiene il corso n_ore integer, Numero di ore del corso. materiale oid, Materiale didattico distribuito con il corso ts timestamp with time zone DEFAULT ('now'::text)::timestamp, CONSTRAINT corso_chiave_surrogata PRIMARY KEY (corsopk), CONSTRAINT corso_chiave_reale UNIQUE (corsoid), CONSTRAINT corso_n_ore_check CHECK (n_ore > 0 AND n_ore < 8) ) 3 di 182

4 Database didattico CREATE TABLE partecipante ( partecipantepk serial NOT NULL, Chiave surrogata della tabella nome character varying(20), Nome del partecipante. cognome character varying(20), ts timestamp with time zone DEFAULT ('now'::text)::timestamp, partecipanteid character varying(30), CONSTRAINT partecipante_chiave_surrogata PRIMARY KEY (partecipantepk), CONSTRAINT partecipante_chiave_reale UNIQUE (partecipanteid) ) 4 di 182

5 Database didattico CREATE TABLE j_corso_partecipante ( j_corso_partecipante_pk serial NOT NULL, Chiave surrogata corsopk integer NOT NULL, partecipantepk integer NOT NULL, CONSTRAINT j_corso_partecipante_chiave_surrogata PRIMARY KEY (j_corso_partecipante_pk), CONSTRAINT j_corso_partecipante_corsopk FOREIGN KEY (corsopk) REFERENCES corso (corsopk) MATCH SIMPLE ON UPDATE NO ACTION ON DELETE NO ACTION, CONSTRAINT j_corso_partecipante_partecipantepk FOREIGN KEY (partecipantepk) REFERENCES partecipante (partecipantepk) MATCH SIMPLE ON UPDATE NO ACTION ON DELETE NO ACTION ) 5 di 182

6 JDBC: applicazioni client 6 di 182

7 JDBC JDBC (Java DataBase Connectivity) è un'api a livello SQL, ossia consente di inglobare comandi SQL nelle proprie applicazioni Java. JDBC fornisce un'unica API CLI per l'accesso a database relazioni eterogenei. L'applicazione non necessita di adattamenti qualora il motore database cambi! Applica il famoso concetto Write Once, Run Everywhere alla connettività database. Si noti che l'idea non è nuovissima: ODBC si propone già come API unificata. Non è indispensabile utilizzare JDBC! 7 di 182

8 Application & Driver APIs JDBC può essere divisa in due parti fondamentali: Application API e Driver API. Le Application API comprendono tutti gli elementi che un'applicazione Java usa per la connessione ad un database. Le Driver API forniscono la base per la scrittura di un driver specifico per un determinato motore relazionale (es. PostgreSQL). Grazie alla suddivisione in due parti, JDBC consente la scrittura di applicazioni portabili e database-independent. All'URL All'URL èèpossibile possibileverificare verificarel'esistenza l'esistenzadidiun undriver driverjdbc JDBC per ogni motore relazionale conosciuto. per ogni motore relazionale conosciuto. 8 di 182

9 Application API vs Driver API Java Application Application ApplicationAPI API Driver DriverAPI API Database Engine 9 di 182

10 Livelli JDBC Le Driver API riconoscono quattro modalità di implementazione differenti, chiamate livelli o type dei driver JDBC: type 1 (JDBC-ODBC bridge): viene sfruttato un accesso ODBC (che deve esistere!). type 2 (Native API Drivers): il driver richiama, tramite JNI, codice nativo (es. C/C++) per la connettività. type 3 (Network Drivers): il driver si collega (via TCP/IP) ad un componente lato server che si interfaccia a sua volta con il database server. type 4 (Pure Java): il driver si collega direttamente al database server e comunica utilizzando un protocollo opportuno. 10 di 182

11 Livelli JDBC: schema riassuntivo JDBC Type 1 ODBC Driver JDBC Type 2 Native Driver Database Engine Java Application JDBC Type 3 Translator (e.g., local JDBC type 2) JDBC Type 4 11 di 182

12 JDBC API 12 di 182

13 Classi principali JDBC Le principali classi/interfaccie della libreria JDBC (java.sql.* e javax.sql.*) sono: DriverManager: rappresenta un repository di istanze di Driver per ogni database server. Ci si rivolge a questa classe per creare una connessione ad uno specifico database (tramite un URL). Driver: rappresenta il componente incaricato di stabilire la connessione con il database server. Può essere caricato all'interno del programma (es. tramite reflection) o specificando la proprietà jdbc.drivers nel momento di invocazione della JVM: java Djdbc.drivers=org.postgresql.Driver myapp 13 di 182

14 Classi principali JDBC (2) Connection: rappresenta una connessione al server database. Tramite di essa è possibile interagire con il database stesso. Statement: implementa una query SQL di qualunque tipo; viene usato per l'esecuzione di un comando sul database server. Si specializza in due sotto-interfaccie: PreparedStatement: una query SQL precompilata e dotata di wrapping dei parametri. CallableStatement: una query SQL che coinvolge una stored procedure. 14 di 182

15 Classi principali JDBC (3) ResultSet: implementazione di un cursore SQL. Contiene un riferimento alla riga dei risultati dall'esecuzione di un comando SQL. Disponde di una serie di metodi per il posizionamento rispetto alle righe e per l'estrazione dei valori di ogni colonna. ResultSetMetaData: informazioni aggiuntive su un ResultSet, quali nomi e numero delle colonne, nome dello schema corrente, etc. DatabaseMetaData: fornisce informazioni aggiuntive sul database stesso, quali versione, stored procedures, foreign keys, etc. SQLException: classe base di ogni eccezione JDBC. 15 di 182

16 Tipica applicazione JDBC Caricamento Caricamentodel del driver necessario driver necessario Istanziazione Driver Connessione Connessionealal database database (Connection) (Connection) Registrazione presso DriverMagaer [while ResultSet.next()] <INVIO> Lettura Letturadel del ResultSet ResultSet Simile all'esecuzione del comando psql -h host -U utente db Simile alla scrittura di una query sulla linea di comando di psql Esecuzione Esecuzionedello dello Statement Statement Creazione Creazionedidiuno uno Statement Statement Chiusra Chiusrarisorse risorseassociate associateaa ResultSet ResultSet ee Statement Statement Chiusura Chiusura connessione connessione (Connection) (Connection) 16 di 182

17 Classi accessorie La libreria fornisce una serie di classi aggiuntive per il mapping fra i tipi SQL e i tipi Java (Types), la gestione di Large Object Data (Clob, Blob), date (Date), timestamp (Timestamp) e array (Array). Come estensioni sono presenti anche le classi per la gestione dei data source (DataSource), dei row set (RowSet) e dei relativi eventi (e.g., RowSetEvent, StatetementEvent). 17 di 182

18 Connessione al database public static void main(string[] args) throws Exception{ try{ // classe del driver String drivername = "org.postgresql.driver"; // url di connessione String databaseurl = "jdbc:postgresql://localhost/pgdaydb"; // caricamento della classe del driver Class driverclass = Class.forName(driverName); // creazione dell'istanza del driver Driver driver = (Driver) driverclass.newinstance(); 18 di 182

19 Connessione al database // // // // a questo punto il driver è registrato presso il DriverManager (il driver di PostgreSQL si registra automaticamente al DriverManager appena la sua classe viene caricata) // essendo il driver caricato e registrato posso // ottenere una connessione al database Connection connection = DriverManager.getConnection(databaseURL, "luca", // username "xxx" // password ); // una volta ottenuta una connessione al database // e' possibile interagire con esso per via di // oggetti di tipo Statement 19 di 182

20 Creazione di uno Statement // creazione di una query e di uno statement // da usare (la query mostra i corsi // che contengono java nella descrizione // e i relativi iscritti) String query = "SELECT c.corsoid, c.descrizione, c.data, c.n_ore, p.nome, p.cognome " + " FROM (corso c LEFT JOIN j_corso_partecipante j ON c.corsopk = j.corsopk) " + " LEFT JOIN partecipante p ON p.partecipantepk = j.partecipantepk " + " WHERE c.descrizione ilike '%java%' "; // notare che lo Statement non e' ancora associato // a nessuna query Statement statement = connection.createstatement(); // effettuo la query ResultSet rs = statement.executequery(query); 20 di 182

21 Analisi dei risultati: ResultSet // visualizzo i dati ottenuti dalla query: l'oggetto // ResultSet (rs) rappresenta un cursore dei risultati // che può essere scorso. while( rs.next() ){ System.out.println("######"); // posso ottenere i dati di una riga chiamando i // metodi getxxx (XXX = tipo di dato) e specificando // il numero della colonna (partendo da 1) o il suo // nome simbolico System.out.println("Id-Corso e descrizione: " + rs.getstring(1) + " " + rs.getstring(2)); System.out.println("Data e numero ore: " + rs.getdate(3) + " " + rs.getint(4)); System.out.println("Iscritto: " + rs.getstring("nome") + " " + rs.getstring("cognome")); } 21 di 182

22 Fine del programma e gestione delle eccezioni // chiusura della connessione connection.close(); } }catch(sqlexception exception){ // eccezione SQL (problema nella query, errore del // server, etc.) }catch(classnotfoundexception ex){ // classe del driver JDBC non trovata }catch(instantiationexception ex){ // errore di reflection (classe driver non // istanziabile) }catch(illegalaccessexception ex){ // errore di reflection (classe driver non // accessibile) } } 22 di 182

23 Esecuzione Riassunto: Caricamento del driver PostgreSQL (necessario solo all'avvio del thread principale dell'applicazione); Creazione di una connessione specificando l'url di connessione; Creazione di uno Statement; Esecuzione dello Statement; Lettura dei risultati tramite il ResultSet; Chiusura delle risorse. 23 di 182

24 Come fa il DriverManager a scegliere il Driver opportuno? Il DriverManager stabilisce quale sia il Driver da utilizzare per una connessione sulla base dell'url di connessione (ogni driver accetta il proprio subprotocol): protocol:subprotocol://hostname/db_name HOSTNAME: specifica l'indirizzo IP/nome dell'host ove è in esecuzione il database. DB_NAME: nome del database cui ci si intende connettere. jdbc:postgres://localhost/pgdaydb protocol: specifica il dominio di appartenenza di questo URL. Indica che l'url si riferisce ad una connessione database (JDBC). subprotocol: specifica il driver che si deve utilizzare. Viene utilizzato da DriverManager per fare il lookup dell'istanza di Driver da restituire per gestire la connessione al database. 24 di 182

25 Considerazioni sul caricamento del driver Il caricamento e l'istanziazione del driver JDBC può avvenire attraverso reflection o direttamente: // reflection Class driverclass = Class.forName( org.postgresql.driver ); Driver driverinstance = driverclass.newinstance(); // istanziazione diretta Driver driverinstance = new org.postgresql.driver(); I driver hanno sempre un costruttore di default senza argomenti, I driver hanno sempre un costruttore di default senza argomenti, e quindi sono sempre istanziabili mediante reflection. e quindi sono sempre istanziabili mediante reflection. 25 di 182

26 Considerazioni sul ResultSet Un ResultSet rappresenta un cursore sui risultati di una query. Il posizionamento fra le righe del cursore avviene tramite metodi specifici, quali next() e previous(). Ogni ResultSet è legato allo Statement che lo ha generato; se lo Statement viene alterato il ResultSet è automaticamente invalidato! Esistono metodi per recuperare il valore di ogni colonna secondo il tipo di appartenenza (String, int, Date,...): <tipo_java> get<tipo_java>(int colonna) <tipo_java>get<tipo_java>(string nomecolonna) Ogni tipo SQL viene mappato in un tipo Java (e viceversa) mediante una specifica tabella di conversione (http://java.sun.com/j2se/1.3/docs/guide/jdbc/getstart/mapping. html). Tale tabella può essere estesa dall'utente per mappare i tipi user defined. SiSipresti prestiattenzione attenzionealalfatto fattoche, che,contrariamente contrariamentealla allalogica logica degli array, le colonne sono numerate partendo da 1! degli array, le colonne sono numerate partendo da 1! 26 di 182

27 ResultSet: errori frequenti Si richiama getxxx(..) con un indice di colonna errato (maggiore) rispetto al numero di colonne estratte dalla query. Si richiama getxxx(..) prima di aver chiamato almeno una volta next(). 27 di 182

28 Esecuzione di un INSERT/UPDATE/DELETE // creazione di una query e di uno statement // da usare per inserire un nuovo corso String query = "INSERT INTO corso(corsoid,descrizione) VALUES('Java_adv', 'Corso avanzato su Java/JDBC') "; Statement statement = connection.createstatement(); // chiedo al server di eseguire la query e // di fornirmi il numero di righe "toccate" // tutte le query che modificano i dati vanno eseguite // attraverso il metodo executeupdate(..) int rows = statement.executeupdate(query); if( rows > 0) System.out.println("Inserimento effettuato con successo:" + rows + " righe inserite"); // chiusura della connessione connection.close(); 28 di 182

29 Esecuzione Riassunto: Caricamento del driver PostgreSQL (necessario solo all'avvio del thread principale dell'applicazione); Creazione di una connessione specificando l'url di connessione; Creazione di uno Statement; Esecuzione dello Statement; Lettura del valore di ritorno dell'esecuzione dello Statement, tale valore indica il numero di righe toccate dalla query; Chiusura delle risorse. 29 di 182

30 Compilazione del driver 30 di 182

31 Driver JDBC per PostgreSQL PostgreSQL fornisce un driver JDBC conforme ai livelli 2,3 e 4. Il sito web del progetto è dal quale è possibile scaricare il driver (in formato binario o sorgente), navigare la documentazione Javadoc della parte public delle API. E' presente una mailing list specifica: pgsql gli attuali mantainer del Driver sono Dave Cramer, Kris Jurka, Oliver Jowett. 31 di 182

32 Decompressione dei sorgenti I sorgenti vengono rilasciati sotto forma di archivio compresso (tarball): postgresql jdbc src.tgz E' possibile decomprire programma tar: i sorgenti usando il tar xzvf postgresql jdbc src.tgz ottenendo una directory che contiene l'albero dei sorgenti ls l postgresql jdbc rw r r 1 luca luca :02 build.properties rw r r 1 luca luca :00 build.xml drwxr xr x 2 luca luca :22 doc rw r r 1 luca luca :25 LICENSE drwxr xr x 3 luca luca :22 org rw r r 1 luca luca :24 README rwxr xr x 1 luca luca :15 update translations.sh 32 di 182

33 Compilazione: requisiti Per compilare il driver JDBC è necessario utilizzare Apache Ant (http://ant.apache.org), uno strumento di compilazione automatico per Java. Ant è uno strumento concettualmente simile a make, ma ottimizzato per la gestione dei progetti Java. Esso stesso è scritto in Java, e questo ne facilita la fruibilità nello sviluppo di componenti Java. Ant necessita della presenza di un file di build (solitamente build.xml) che contiene i task del processo di compilazione. E' possibile specificare proprietà di compilazione mediante file di proprietà Java (file properties). 33 di 182

34 Compilazione: build Il file di build del driver è build.xml, e può essere omesso nell'invocazione di ant: src/postgresql jdbc src]$ ant Buildfile: build.xml all: prepare: check_versions: check_driver: driver: compile: [javac] Compiling 144 source files to /sviluppo/java/contrib src/postgresql jdbc src/build [javac] Note: Some input files use or override a deprecated API. [javac] Note: Recompile with Xlint:deprecation for details. [javac] Note: Some input files use unchecked or unsafe operations. [javac] Note: Recompile with Xlint:unchecked for details. jar: [jar] Building jar: /sviluppo/java/contrib src/postgresql jdbc src/jars/postgresql.jar BUILD SUCCESSFUL Total time: 5 seconds src/postgresql jdbc src]$ 34 di 182

35 Compilazione: risultato Al termine del processo di compilazione viene generato un file postgresql.jar nella sottodirectory jars: src/postgresql jdbc src]$ ls l jars/ total 436 rw r r 1 luca luca :22 postgresql.jar src/postgresql jdbc src]$ Il file jar prodotto deve essere incluso nel classpath corrente affinché i programmi Java possano caricare il driver. $ export CLASSPATH=`pwd`/jars/postgresql.jar:$CLASSPATH $ echo $CLASSPATH /sviluppo/java/contrib src/postgresql jdbc src/jars/postgresql.jar: $ 35 di 182

36 Compilazione: risultato (2) Un altro file importante viene generato: Driver.java $ ls l org/postgresql/driver.java* rw r r 1 luca luca :21 org/postgresql/driver.java rw r r 1 luca luca :18 org/postgresql/driver.java.in $ Prima della compilazione infatti il solo file Driver.java.in è presente. Il file Driver.java viene generato dinamicamente durante il processo di build, a seconda del livello JDBC del driver. 36 di 182

37 Compilazione in Eclipse Definire un nuovo progetto basato su un file Ant esistente. (1) (2) Selezionare il file di build dalla directory dei sorgenti; specificare le proprietà del progetto. 37 di 182

38 Compilazione in Eclipse (2) (3) Ricercare il file build.xml tramite il modulo Ant di Eclipse. 38 di 182

39 Compilazione in Eclipse (3) (4) Eseguendo il file di build il progetto viene compilato. 39 di 182

40 JDBC 2, 3 o 4? Il driver JDBC di Postgresql supporta solo i livelli JDBC 2,3 e 4. L'albero dei sorgenti include i package per ogni versione JDBC. $ ls org/postgresql/ l... drwxr xr x 3 luca luca :23 jdbc2 drwxr xr x 2 luca luca :23 jdbc3 drwxr xr x 2 luca luca :23 jdbc4... $ La decisione su quale livello di driver (org.postgresql.driver) viene presa durante il processo di build in base alla versione della JVM. In particolare la versione viene stabilita sulla base della Java Virtual Machine installata sul sistema. 40 di 182

41 Driver.java.in Il file org.postgresql.driver.java.in è un file che viene tramutato nel driver Java vero e proprio durante il processo di build Ant. Al suo interno il file Driver.java.in contiene dei segnaposti per le classi JDBC del livello opportuno. 41 di 182

42 Scelta del livello JDBC Il file contiene build.xml un target, check_versions, che controlla quale versione di JVM sia disponibile e, di conseguenza, quale versione di driver sia la più appropriata. A seconda del livello stabilito viene impostata a true la proprietà jdbcx. 42 di 182

43 Scrittura del livello JDBC Il target driver si occupa della scrittura del file Driver sostituendo i marcaposto al suo interno con le classi del livello JDBC scelto. Si noti che viene utilizzata la funzionalità di filtro (filter) di Ant per la sostituzione dei marcaposto (token) con le classi concrete. Diverse altre classi sono specificate con lo stesso procedimento. 43 di 182

44 Scrittura del livello JDBC (2) Viene fatto un controllo sulla proprietà jdbcx, impostata precedentemente dal target check_versions. (1) 44 di 182

45 Scrittura del livello JDBC (3) (2) Vengono impostati i token marcaposto da sostituire nel file Driver.java.in; ogni token specificato in build.xml trova corrispondenza con in Driver.java.in 45 di 182

46 Scrittura del livello JDBC (4) (3) Il file Driver.java.in viene copiato in Driver.java applicando le condizioni di filtro. 46 di 182

47 JDBC: tipi di Statement 47 di 182

48 PreparedStatement Un PreparedStatement è un oggetto che memorizza uno statement SQL precompilato, che può essere parametrizzato e che può eseguire più efficientemente di uno Statement normale. L'idea è di precompilare un comando SQL parziale e di completarlo successivamente, al momento in cui l'esecuzione sia necessaria. Lo statement precompilato può poi essere riutilizzato più volte, cambiando eventualmente i parametri di esecuzione. Un PreparedStatement è una sottointerfaccia di Statement! Essendo Essendouno unostatement statementparametrizzabile, parametrizzabile,preparedstatement PreparedStatementfornisce forniscedei deimetodi metodi setxxx setxxxeegetxxx getxxxper perimpostare impostarei iparametri parametrididiesecuzione. esecuzione. 48 di 182

49 Prepared Statement // creazione di una query di inserimento e dello // statement precompilato per la sua esecuzione String query = "INSERT INTO corso(corsoid,descrizione) VALUES(?,?) "; PreparedStatement statement = connection.preparestatement(query); // inserisco alcuni corsi fornendo gli opportuni // parametri al server int rows = 0; for(int i = 0; i < 10; i++){ String corsoid = "corso_" + i; String descrizione = "Nessuna descrizione "; // impostazione dei parametri nello statement statement.setstring(1, corsoid); statement.setstring(2, descrizione); // eseguo lo statement (non devo specificare una query // poiché lo statement è già stato precompilato) rows += statement.executeupdate(); } 49 di 182

50 Considerazioni: PreparedStatement Un PreparedStatement utilizza una sintassi speciale per le query SQL: ogni carattere? viene usato come un marcatore per un parametro che verrà specificato in seguito. In maniera duale ad un ResultSet vengono forniti dei metodi setxxx(numpar, value). Il vantaggio dei PreparedStatement è che possono essere memorizzati e precompilati dal database server, aumentado le prestazioni nel caso di cicli (l'ottimizzatore potrebbe però stabilire piani diversi a seconda della selettività dei parametri). Si Sipresti prestiattenzione attenzionealalfatto fattoche che i iparametri parametrisono sononumerati numeratipartendo partendoda da1!1! 50 di 182

51 Statement vs PreparedStatement Statement: PreparedStatement: query statiche o poco variabili; query parametriche; nessuna necessità escaping dei parametri. query base da eseguire ciclicamente a seconda di parametri run-time; di escaping di parametri usati nella query stessa. L'utilizzo di PreparedStatement è preferibile in molte situazioni! 51 di 182

52 CallableStatement L'interfaccia CallableStatement viene usata in maniera analoga ai PreparedStatement per l'invocazione di una Stored Procedure. La sintassi utilizzata per l'invocazione è la seguente: { call stored_procedure(?,?,...) } Viene specificato il nome della stored procedure da invocare, seguito dalla lista di eventuali parametri. La funzione viene invocata con il metodo executequery() che restituisce un ResultSet. 52 di 182

53 JDBC: Utilizzo avanzato 53 di 182

54 Esecuzione di comandi arbitrari Si supponga di voler creare una vista definita come segue: CREATE VIEW vw_partecipanti AS SELECT c.corsoid, c.descrizione, c.data, p.cognome, p.nome FROM partecipante p JOIN corso c ON c.corsopk = p.corsopk ORDER BY c.corsoid, p.cognome, p.nome Come si può notare l'esecuzione della query non produce alcun risultato (in termine di numero di righe modificate) pur alterando la struttura del database. 54 di 182

55 Esecuzione di comandi arbitrari // creazione di uno statement Statement statement = connection.createstatement(); // preparazione della query String sql = "CREATE VIEW vw_partecipanti AS SELECT c.corsoid, c.descrizione, c.data, p.cognome, p.nome FROM partecipante p JOIN corso c ON c.corsopk = p.corsopk ORDER BY c.corsoid, p.cognome, p.nome"; int result = statement.executeupdate(sql); System.out.println("Risultato di esecuzione: " + result); 55 di 182

56 JDBC: creazione della procedura // creazione di uno statement Statement statement = connection.createstatement(); // preparazione della funzione StringBuffer buffer = new StringBuffer(1000); buffer.append( "CREATE OR REPLACE FUNCTION... ); buffer.append(" RETURNS void AS $BODY$ DECLARE... ); // chiamata della stored procedure int result = statement.executeupdate(buffer.tostring()); System.out.println("Risultato della creazione della procedura: " + result); 56 di 182

57 JDBC: invocazione della procedura // invocazione della funzione String sql = "{ call f_nuovo_corso(?,?,?) }"; // preparazione della chiamata e impostazione dei parametri CallableStatement cstatement = connection.preparecall(sql); cstatement.setint(1, 2); cstatement.setstring(2, "Corso2009"); Calendar calendar = Calendar.getInstance(); calendar.set(calendar.day_of_month, 7); calendar.set(calendar.month, 7); calendar.set(calendar.year, 2009); cstatement.setdate(3, new java.sql.date(calendar.gettimeinmillis()) ); // invocazione della funzione ResultSet resultset = cstatement.executequery(); // in questo caso non ho risultati di 182

58 CallableStatement L'interfaccia CallableStatement viene usata in maniera analoga ai PreparedStatement per l'invocazione di una Stored Procedure. La sintassi utilizzata per l'invocazione è la seguente: { call stored_procedure(?,?,...) } {?= stored_procedure(?,?,...) } Viene specificato il nome della stored procedure da invocare, seguito dalla lista di eventuali parametri. L'invocazione avviene tramite il metodo executequery() che restituisce un ResultSet. E' possibile registrare parametri di input/output e ottenerne il valore direttamente dallo statement. 58 di 182

59 Batch L'interfaccia Statement consente l'esecuzione batch di una serie di comandi SQL: public void addbatch(string sql) mediante tale metodo è possibile assegnare una serie di istruzioni SQL da eseguire sequenzialmente in un momento successivo. L'esecuzione del gruppo di comandi avviene mediante il metodo executebatch(), che restituisce i singoli valori di ritorno dell'esecuzione di ogni comando. public int[] executebatch() 59 di 182

60 Batch: un primo esempio // creo uno statement Statement statement = connetion.createstatement(); // imposto i comandi da eseguire nel batch String sql = INSERT INTO... ; // aggiungo questa istruzione al batch statement.addbatch(sql); // nuova istruzione da aggiungere al batch sql = INSERT INTO... ; statement.addbatch(sql);... // eseguo il batch int result[] = statement.executebatch(); // controllo i risultati di ogni comando for(int i=0; i<result.length; i++) System.out.println( Comando +(i+1)+ risultato + result[i]); 60 di 182

61 Batch & PreparedStatement L'utilizzo dei batch agevola i casi in cui siano presenti cicli. E' possibile utilizzare oggetti PreparedStatement al fine di unire i vantaggi di un'esecuzione batch e della parametrizzazione dei comandi SQL. // query parametri String sql = UPDATE corso SET descrizione=? WHERE corsoid=? ; PreparedStatement statement = connection.preparestatement(sql); for(int i=0; i< 10; i++){ statement.setstring(1, descrizione[i]); statement.setstring(2, id[i]); statement.addbatch(); } // esecuzione int result[] = statement.executebacth(); 61 di 182

62 Batch: considerazioni Solitamente l'utilizzo di un batch risulta più efficiente che l'esecuzione delle singole operazioni in modo separato (ottimizzazione da parte del driver). Si presti attenzione al fatto che un batch è differente da una transazione, tuttavia può essere usato per rendere più compatto (e quindi leggibile) il codice di una transazione. 62 di 182

63 Scrollable ResultSet Uno scrollable ResultSet è un tipo particolare ResultSet che offre una funzionalità di scrolling. di E' possibile muoversi attraverso le righe in avanti e indietro, saltare righe, posizionarsi in modo relativo o assoluto, etc. Il tipo di scrolling deve essere specificato a livello di creazione dello Statement, specificando il tipo di scrolling (e di aggiornabilità) come parametri del metodo createstatement(..), in modo da consentire al database di gestire le risorse. IlIldriver driverpostgresql PostgreSQLutilizza utilizzainternamente internamenteun unvector Vectorper per contenere contenereleletuple tupledel delresultset; ResultSet;mediante medianteun unindice indice riesce a garantire lo scrolling di tali tuple. riesce a garantire lo scrolling di tali tuple. 63 di 182

64 Tipo di scrolling Il tipo di un ResultSet può essere specificato tramite tre valori predefiniti: ResultSet.TYPE_FORWARD_ONLY (1003) è il classico ResultSet che può essere consultato solo in avanti. ResultSet.TYPE_SCROLL_INSENSITIVE (1004) può essere consultato in entrambe le direzioni ma non riflette cambiamenti fatti al database mentre è aperto. ResultSet.TYPE_SCROLL_SENSITIVE (1005) può essere consultato in entrambe le direzioni e riflette ogni cambiamento apportato. Il tipo di scrolling può essere ricavato a tempo di esecuzione tramite il metodo int ResultSet.getType(); 64 di 182

65 Posizionamento all'interno del ResultSet L'interfaccia ResultSet mette a disposizione diversi metodi di posizionamento: beforefirst(), afertlast() restituiscono true se si ci si trova oltre la prima o l'ultima riga. next(), previous() muovono di una riga in avanti o indietro il cursore. absolute(int), relative(int) spostano il cursore alla riga specificata in modo assoluto o relativo (dalla posizione corrente). Un indice negativo considera lo spostamento all'indietro (es. -1 sposta all'ultima riga nel caso di posizionamento assoluto o alla riga precedente nel caso di posizionamento relativo). getrow() ritorna il numero di riga (valore assoluto) a cui si è posizionati correntemente. 65 di 182

66 Esempio di scrollable ResultSet // ottengo il result set di una query ResultSet rs = statement.executequery(); while( rs.next() ){ // esecuzione in avanti (solo righe pari) int numero_riga = rs.getrow(); if( (numero_riga % 2) == 0 ){ System.out.println("######"); System.out.println("Id-Corso e descrizione: " + rs.getstring(1) + " " + rs.getstring(2)); } } // torno indietro e processo solo le righe dispari while( rs.previous() ){ int numero_riga = rs.getrow(); } if( (numero_riga % 2)!= 0 ){...} 66 di 182

67 ResultSet aggiornabili JDBC v2 permette di aggiornare (inserire, modificare, cancellare) le righe di una query usando direttamente il ResultSet corrispondente. In sostanza non si è obbligati a creare un comando di update/insert ma si può modificare il valore di una colonna direttamente operando sui risultati di una query. E' un tentativo di nascondere i dettagli SQL e di rendere il sistema più Object-Oriented. 67 di 182

68 ResultSet aggiornabili (2) Per rendere tutto ciò possibile l'interfaccia ResultSet include una serie di metodi simili a quelli per la definizione dei parametri di un PreparedStatement. Ad esempio: updatestring(int column, String value); updateint(int column, int value);... Esistono poi dei metodi speciali per aggiornare/inserire/cancellare e aggiornare i valori della riga corrente: updaterow(); insertrow(); deleterow(); refresh(); 68 di 182

69 Tipo di aggiornabilità Il tipo di un ResultSet, relativamente alla sua aggiornabilità, può essere specificato tramite due valori predefiniti: ResultSet.CONCUR_READ_ONLY (1007) è ResultSet che non può essere aggiornato. il classico ResultSet.CONCUR_UPDATABLE (1008) può essere aggiornato e quindi supporta inserimento, modifica e cancellazione di righe. Il tipo di aggiornabilità può essere ricavato a tempo di esecuzione tramite il metodo int ResultSet.getType(); 69 di 182

70 Inserimento di una riga L'inserimento di una riga in un ResultSet è un'operazione leggermente più complessa rispetto all'aggiornamento. Occorre infatti istruire il ResultSet affinché prepari posto per i valori della riga che si vuole inserire, assegnare tali valori e confermare (salvare) l'inserimento della nuova riga. Se il ResultSet è di tipo scroll sensitive la riga inserita sarà visibile senza bisogno di aggiornamenti del ResultSet stesso. 70 di 182

71 Inserimento di una riga: un approccio visuale La procedura di inserimento di una nuova riga è simile alla procedura usata in molti programmi visuali di accesso e modifica dei database: (1) viene ottenuto il ResultSet relativo ad una specifica query; (2) si passa oltre l'ultima riga, usando una riga vuota come spazio temporaneo per l'inserimento dei valori. Si usa il metodo movetoinsertrow(); (3) vengono salvati i valori inseriti. Si usa il metodo insertrow(). 71 di 182

72 Inserimento di una riga in un ResultSet // processo il result set ed inserisco una nuova riga (max 4) // ad ogni riga pari (non significa DOPO ogni riga pari!) while (rs!= null && rs.next()) { int numero_riga = rs.getrow(); if( ((numero_riga % 2) == 0) && inserite < 4 ){ // inserisco una nuova riga in fondo al result set rs.movetoinsertrow(); rs.updatestring(1, "CorsoRS" + numero_riga); rs.updatestring(2, "Prova di inserimento da ResultSet"); rs.insertrow(); // torno alla riga cui ero prima dell'inserimento rs.movetocurrentrow(); inserite++; } String corsoid = rs.getstring(1); String descrizione = rs.getstring(2); System.out.println("Riga numero " + numero_riga + " " + corsoid + " = " + descrizione); } 72 di 182

73 JDBC: Transazioni 73 di 182

74 JDBC e transazioni Il driver JDBC lavora in modalità auto-commit: ogni istruzione eseguita tramite uno Statement viene automaticamente confermata. E' come se si eseguissero transazioni monocomando. Per prendere il controllo sulla transazione e segnarne l'inizio e la fine (BEGIN-END) è necessario disabilitare l'auto-commit del driver e forzare un esplicito commit/rollback. 74 di 182

75 Schema di funzionamento // disabilito auto commit connection.setautocommit(false); // effettuo del lavoro, INSERT, UPDATE, ecc. e tengo // traccia se devo fare un rollback... rollback = true; // tutto fatto if(! rollback ) connection.commit(); else connection.rollback(); connection.setautocommit(true); // ripristino auto-commit 75 di 182

76 Transazioni: livello di isolamento E' possibile impostare il livello di isolamento di una transazione. I livelli di isolamento sono memorizzati come costanti (interi) nell'oggetto Connection e possono valere: Connection.TRANSACTION_READ_COMMITTED impedisce che ci siano dirty-reads, ma consente unrepeatable e phantom reads; Connection.TRANSACTION_READ_UNCOMMITTED non consente nessun tipo di dirty, unrepeatable e phantom reads; Connection.TRANSACTION_REPEATABLE_READ consente solo phantom reads; Connection.TRANSACTION_SERIALIZABLE sono serializzabili. le transazioni 76 di 182

77 Transazioni: riassunto & considerazioni L'inizio di una transazione deve essere eplicitato a livello di connessione (Connection) disabilitando la modalità di auto-commit. Tutte le operazioni eseguite tramite uno Statement dopo aver disabilitato l'auto-commit fanno parte della transazione. La fine di una transazione deve forzare un esplicito commit o rollback sulla connessione. Una volta terminata la transazione è necessario riabilitare l'auto-commit, altrimenti le istruzioni succesive faranno parte di una nuova transazione (il driver non ri-abilita da solo l'auto-commit!). 77 di 182

78 JDBC: DataSource 78 di 182

79 DataSource Le API JDBC 2 introducono nel package javax.sql l'interfaccia DataSource che si comporta come un wrapper attorno alla connettività di un un database. In sostanza un DataSource è un'oggetto che contiene tutte le informazioni che servono per la connettività verso la sorgente dati (database) quali URL, username, password, auto-commit mode, etc. Lo scopo dei DataSource è quello di disaccoppiare l'impostazione dei parametri di connettività (tipicamente amministrativi) dal loro utilizzo (tipicamente applicativo). Diverse applicazioni possono condividere la stessa DataSource (ad esempio tramite JNDI); una modifica nel DataSource (ad esempio modifica all'url) non necessita nessun intervento sulle applicazioni che lo utilizzano. 79 di 182

80 ConnectionPoolDataSource Un tipo particolare di sorgente dati è il ConnectionPoolDataSource che consente di gestire le connessioni in pool. L'idea è quella di mantenere le connessioni al database in una cache, in modo da renderle disponibili a diversi componenti man mano che vengono richieste. Non venendo aperte/chiuse di continuo, le connessioni vengono erogate con tempi di risposta più bassi rispetto all'approccio classico. L'utilizzo delle sorgenti dati con pool richiede però qualche passaggio in più rispetto all'uso delle sorgenti dati semplici. Viene comunque garantito il disaccoppiamento fra la parte amministrativa e quella applicativa. 80 di 182

81 DataSource & PostgreSQL I driver JDBC di PostgreSQL mettono a disposizione due tipi principali di DataSource (contenute nel package org.postgresql.ds): PGSimpleDataSource un DataSource senza alcun tipo di pooling. Implementa javax.sql.datasource e dispone di un metodo getconnection() che fornisce la connessione al database. Ad esempio: DataSource datasource = new PGSimpleDataSource();... Connection connection = datasource.getconnection(); 81 di 182

82 DataSource & PostgreSQL PGPoolingDataSource un DataSource con capacità di pooling delle connessioni. Implementa javax.sql.connectionpooldatasource e mette a disposizione un metodo getpooledconnection() che fornisce un oggetto javax.sql.pooledconnection, al quale si può richiedere la connessione tramite getconnection(). Ad esempio: ConnectionPoolDataSource datasource = new PGConnectionPoolDataSource();... PooledConnection pooledconnection = datasource.getpooledconnection(); Connection connection = pooledconnection.getconnection(); 82 di 182

83 Impostazione delle proprietà di una sorgente dati Le proprietà delle sorgenti dati vengono impostati tramite metodi set (e lette dai relativi metodi get secondo le specifiche Java Beans). Solitamente gli ambienti server mettono a disposizione dei file di configurazione (es. XML) che consentono di specificare le varie proprietà. L'ambiente container (es. Tomcat) si farà poi carico di leggere tale file di configurazione e di impostare le proprietà di connessione nella sorgente dati. servername Indirizzo IP o nome del server database databasename Nome del database cui collegarsi portnumber Porta a cui collegarsi tramite TCP/IP user Utente da usare per la connessione password Password per l'utente di cui sopra initialconnections Numero di connessioni da creare all'avvio maxconnections Massimo numero di connessioni istanziabili 83 di 182

84 Esempio di uso di DataSource // creazione di un data source per PostgreSQL PGConnectionPoolDataSource datasource = new org.postgresql.ds.pgconnectionpooldatasource(); // impostazione dei parametri di connessione datasource.setdatabasename("pgdaydb"); datasource.setuser("luca"); datasource.setpassword(null); datasource.setservername("localhost"); datasource.setdefaultautocommit(true); // ora il datasource andrebbe esportato e reso disponibile // ad altre applicazioni, ad esempio tramite JNDI... // prelevo la sorgenti dati ConnectionPoolDataSource source = (ConnectionPoolDataSource) datasource; // oppure // PooledConnection pooledconnection = // source.getpooledconnection(); 84 di 182

85 Spring La libreria Spring fornisce un sottoinsieme di classi di utilità per la connessione a database e la realizzazione di DAO. <! il template jdbc che deve essere inizializzato con una datasource > <bean id="jdbctemplate" class="org.springframework.jdbc.core.jdbctemplate"> <constructor arg> <ref bean="datasource" /> </constructor arg> </bean> <! inmpostazione della datasource > <bean id="datasource" class="org.springframework.jdbc.datasource.drivermanagerdatasource"> <property name="driverclassname" value="org.postgresql.driver" /> <property name="url" value="jdbc:postgresql:// /hrpmdb" /> <property name="username" value="hrpm" /> <property name="password" value="hrpm" /> </bean> 85 di 182

86 Spring lato applicativo Lato applicativo occorre ottenere il jdbctemplate e usare uno dei suoi metodi per effettuare le query. // insert the address in the database this.jdbctemplate.update( this.getinsertquery(), toinsert.getprimarykey(), toinsert.getstreet(), toinsert.getcity(), toinsert.getcountry(), toinsert.getstate(), toinsert.getphone(), toinsert.getzipcode(), toinsert.getfax() ); 86 di 182

87 Java Transaction API 87 di 182

88 Java Transaction API (JTA) La Java Transaction API (JTA) è un insieme di interfaccie e classi che forniscono una astrazione verso un sistema di transazioni distribuite. Una transazione distribuita è una transazione che coinvolge più risorse (database) allo stesso momento. La necessità di mantenere coerenti le risorse (database) richiede protocolli appositi per la decisione di commit/rollback globale. La JTA si appoggia su una implementazione specifica del server, chiamata Java Transaction Service (JTS). Il JTS è responsabile di implementare il Transaction Manager, che è il componente che prende la decisione globale sul commit/rollback. 88 di 182

89 Transazioni distribuite in Java Java Application User UserTransaction Transaction Interface Interface Transaction TransactionManager Manager JDBC JDBCDriver Driver Application Server Database Engine Database Engine 89 di 182

90 Transazioni distribuite in Java L'interfaccia javax.transaction.usertransaction consente di definire i confini di una transazione distribuita, ossia quale sezione di codice debba essere eseguito come transazione. La sua implementazione dipende dal container che si sta utilizzando. L'interfaccia javax.transaction.transactionmanager consente la gestione delle risorse di transazione al container. L'interfaccia javax.transaction.xa.xaresource rappresenta una risorsa XA da gestire. 90 di 182

91 Transazioni distribuite: Commit a due fasi Il protocollo di commit a due fasi (Two Phase Commit) è un algoritmo distribuito che consente a tutti i nodi che partecipano alla transazione di accordarsi all'unisono per un commit o un rollback. (fase 1: pre-commit) Il coordinatore invia un query-to-commit a tutti i partecipanti. Ogni partecipante effettua le operazioni, aggiorna i propri log (undo e redo) e invia un messaggio di commit o rollback al coordinatore. (fase 2: commit) Quando il coordinatore ha tutti i messaggi dei partecipanti prende la decisione: se tutti hanno inviato un commit il coordinatore conferma il commit ai partecipanti che rendono permanenti le modifiche e inviano un acknowledgement. Il coordinatore chiude la transazione quando riceve tutti gli acknoweldgement. se almeno un partecipante ha inviato un rollback il coordinatore invia un rollback ai partecipanti, che annullano la loro transazione locale e confermano il rollback al coordinatore. 91 di 182

92 Risorse X/Open CAE X/Open CAE specifica gli oggetti e le interfaccie da usare nelle transazioni distribuite (Distributed Transaction Processing: the XA specification): definisce cosa un gestore di risorse debba fare per supportare le transazioni distribuite. Il supporto XA del driver è fondamentale per consentire l'uso con transazioni distribuite. Il driver JDBC di PostgreSQL supporta XA dalla versione 8.1, anche se senza supporto per il transaction interleaving (capacità di usare la stessa connessione per differenti transazioni contemporanee). 92 di 182

93 JTA & Driver JDBC Nonostante il Transaction Manager sia il componente più importante, il driver JDBC deve fornire supporto a XADatasource, XAConnection e XAResource. Le classi di più alto livello JTA, quali ad esempio UserTransaction e TransactionManager non sono nello scope di un driver JDBC quanto di un application server. 93 di 182

94 Identificazione di una transazione Una transazione è identificata da un Transaction ID composto da tre parti fondamentali: format ID: specifica il naming schema delle transazioni (es. OSI CCR Commitment, Concurrency e Recovery). branch qualifier: un branch rappresenta una singola richiesta ad un resource manager. global transaction id: un identificativo globale della transazione in tutto il sistema. L'implementazione di un transaction dipende dal container/sistema utilizzato. id (javax.transaction.xa.xid) 94 di 182

95 Creazione di uno Xid public class PgDayXid implements Xid{ // Il formatid specifica quale specifica si sta usando. // Se vale 0 allora si sta usando la specifica OSI CCR // (OSI Commitment, Concurrency and Recovery). // Se vale 1 allora l'xid non è valido, // mentre se è superiore a zero allora indica // una specifica proprietaria. protected int formatid = 0; // identificativo globale della transazione corrente. (0 64 bytes) protected byte[] globaltransactionid = null; // identificativo del ramo della transazione corrente. (0 64 bytes) protected byte[] branchqualifier = null; public byte[] getbranchqualifier() { return this.branchqualifier; } public int getformatid() { return this.formatid; } public byte[] getglobaltransactionid() { return this.globaltransactionid; } 95 di 182

96 Creazione di uno Xid public void setglobaltransactionid(byte[] gtid){ // tengo conto solo dei primi 64 bytes... if( gtid!= null && gtid.length > 64 ){ System.arraycopy( gtid, 0, this.globaltransactionid, 0, 64 ); } else this.globaltransactionid = gtid; } public void setbranchqualifier(byte[] bq){... } public void setformatid(int id){... } } 96 di 182

97 Utilizzo di JTA public static void main(string[] args) throws Exception { // 1) creazione di un datasource agganciato al database PGXADataSource datasource = new PGXADataSource(); datasource.setdatabasename("pgday"); // nome del database datasource.setuser("luca"); // username datasource.setpassword("fluca"); // password dell'utente datasource.setservername("localhost"); // indirizzo di connessione // del database // 2) ottengo una connessione al database System.out.println("Tentativo di connessione al database..."); XAConnection connection = datasource.getxaconnection(); System.out.println("Connesso!"); // 3) ottengo una risorsa per proteggere la transazione XAResource resource = connection.getxaresource(); 97 di 182

98 Utilizzo di JTA // 4) devo avere un id della transazione che sto per usare PgDayXid identifier = new PgDayXid(); identifier.setbranchqualifier( new byte[] {0x01, 0x02, 0x03, 0x04, 0x05}); identifier.setglobaltransactionid( new byte[] {0x05, 0x04, 0x03, 0x02, 0x01}); identifier.setformatid(100); // 5) eseguo la transazione try{ // 6) inizio della transazione resource.start(identifier, XAResource.TMNOFLAGS); // 7) esecuzione di operazioni JDBC Connection jdbcconnection = connection.getconnection(); jdbcconnection.setautocommit(false); // bug del driver! Statement statement = jdbcconnection.createstatement(); String sql = "INSERT INTO corso(corsoid, descrizione) VALUES('XA1', 'Corso su JTA')"; int inserted = statement.executeupdate(sql); System.out.println("Sono state inserite " + inserted + " righe"); 98 di 182

99 Utilizzo di JTA // 8) ho terminato la transazione resource.end(identifier, XAResource.TMSUCCESS); // 9) controllo se il transaction manager consente il commit // (fase di precommit) int commit = resource.prepare(identifier); System.out.println("Valore del prepare " + commit); if( commit == XAResource.XA_OK ) // commit definitivo resource.commit(identifier, // identificativo transazione false); // false = commit 2 fasi else resource.rollback(identifier); }catch(xaexception e){ e.printstacktrace(); } } 99 di 182

100 Sospensione di una transazione E' possibile sospendere una transazione distribuita per dare modo al processo corrente di eseguire operazioni locali. E' necessario terminare la transazione distribuita e avviarla nuovamente specificando come flag rispettivamente TMSUSPEND e TMRESUME. // 8) sospensione della transazione distribuita resource.end(identifier, XAResource.TMSUSPEND); // 8 bis) effettuo degli statement fuori dalla transazione // distribuita usando lo stesso oggetto Statement statement.executeupdare(...); // 8 tris) riprendo la transazione distribuita resource.start(identifier, XAResource.TMRESUME); 100 di 182

101 JDBC & SSL 101 di 182

102 Connessioni SSL PostgreSQL supporta nativamente le connessioni tramite SSL/TLS da parte dei client (si veda il capitolo 16 del manuale). Solitamente il server PostgreSQL accetta sia connessioni in chiaro che cifrate sulla stessa porta, negoziando dinamicamente il tipo di connessione ricevuta. Una connessione in chiaro invia i pacchetti (es. le query e i risultati) senza cifrarli, e quindi questi sono osservabili sulla rete. Una connessione SSL utilizza uno schema di cifratura per rendere illeggibili da terzi i pacchetti in transito. 102 di 182

103 Connessioni SSL: impostazioni del server Il server deve essere stato compilato con il supporto per SSL, e i certificati devono essere stati generati e si devono trovare nella directory $PGDATA. 103 di 182

104 Connessioni SSL: test Per verificare il funzionamento del supporto SSL è possibile usare il client da riga di comando. Di default viene usata una connessione in chiaro La suite di cifratura è disponibile (connessione esplicita a localhost) 104 di 182

105 Java & SSL Ci sono due modi principali di utilizzo di SSL nelle connessioni a PostgreSQL: connessione verificata: il certificato del server è stato correttamente importato nel keystore (personale o di sistema) di Java, ad indicare che il certificato è noto e corretto. In tal caso, il driver JDBC di PostgreSQL effettua i controlli necessari per validare il certificato ed evitare attacchi man-in-the-middle. connessione non verificata: non è possibile importare il certificato nel keystore, e quindi ci si fida al volo (con i rischi che ne derivano) del certificato presentato dal server. In questo caso occorre usare una socket factory messa a disposizione dal driver JDBC di PostgreSQL. 105 di 182

106 Connessione verificata Il driver JDBC di PostgreSQL si occupa di tutta la parte di scambio di chiavi e connessione, ma occorre importare il certificato del server nel keystore: (1) il certificato del server deve essere tradotto in una forma che keytool può comprendere. A tal fine lo si converte come file DER (ASN1-DER; formato senza header) dal formato PEM (standard per openssl, presenta un header testuale). 106 di 182

107 Connessione verificata (2) il certificato deve essere importato nel keystore (in questo caso privato dell'utente). Al certificato viene associata l'alias pgday, che rappresenta una sorta di username (in realtà è il proprietario del certificato). Il keystore generato, essendo usato per la verifica di un'identità e non strettamente per la cifratura, viene anche denominato trustore. 107 di 182

108 Connessione verificata (3) l'url di connessione deve contenere il parametro ssl=true, al fine di indicare al driver di usare la connessione SSL (viene usata la factory socket di default). Connection connection = DriverManager.getConnection( "jdbc:postgresql://localhost/pgday?loglevel=2&ssl=true", "luca", "fluca"); (4) occorre specificare come parametri alla JVM quale keystore usare e quale password. java Djavax.net.ssl.trustStore=$HOME/keystore Djavax.net.ssl.trustStorePassword=aglets it.pgday.lferrari.pgjdbc1 108 di 182

109 Connessione verificata La connessione impiega qualche secondo per essere convertita da normale a cifrata. Il traffico in circolazione non è più in chiaro. 109 di 182

110 Connessione non verificata E' possible stabilire una connessione SSL senza aver verificato (importato) il certificato del server. A tal scopo è sufficiente impostare la factory di socket SSL come parametro della URL di connessione a org.postgresql.ssl.nonvalidatingfactory. Non è più necessario specificare il keystore e la sua password. Connection connection = DriverManager.getConnection( "jdbc:postgresql://localhost/pgday?loglevel=2&ssl=true &sslfactory=org.postgresql.ssl.nonvalidatingfactory", "luca", "fluca"); java it.pgday.lferrari.pgjdbc1 110 di 182

111 org.postgresql.driver 111 di 182

112 Registrazione del Driver PostgreSQL Il Driver si auto-registra in modo statico richiamando il metodo (static) registerdriver di DriverManager. La registrazione statica anziché nel costruttore del Driver stesso (come molti alti driver fanno) impedisce una registrazione multipla dello stesso driver all'interno della JVM. static { static { try{ try{ java.sql.drivermanager.registerdriver(new Driver()); java.sql.drivermanager.registerdriver(new Driver()); } } catch (SQLException e) catch (SQLException e) { e.printstacktrace(); } { e.printstacktrace(); } } // org.postgresql.driver } // org.postgresql.driver 112 di 182

113 Come il DriverManager sceglie il Driver appropriato... private static Connection getconnection(string url, Properties info, private static Connection getconnection(string url, Properties info, ClassLoader callercl) throws SQLException { ClassLoader callercl) throws SQLException { java.util.vector drivers = null; java.util.vector drivers = null; synchronized (DriverManager.class){ synchronized (DriverManager.class){ drivers = readdrivers; drivers = readdrivers; } } SQLException reason = null; SQLException reason = null; for (int i = 0; i < drivers.size(); i++) { for (int i = 0; i < drivers.size(); i++) { DriverInfo di = (DriverInfo)drivers.elementAt(i); DriverInfo di = (DriverInfo)drivers.elementAt(i); Connection result = di.driver.connect(url, info); Connection result = di.driver.connect(url, info); if (result!= null) { if (result!= null) { class DriverInfo { return (result); class DriverInfo { return (result); Driver driver; } Driver driver; } Class driverclass; // codice di gestione Class driverclass; // codice di gestione String driverclassname; // errori... String driverclassname; // errori... } // java.sql.drivermanager }} } // java.sql.drivermanager }} // java.sql.drivermanager // java.sql.drivermanager 113 di 182

114 connect(..) Il metodo connect(..) del driver PostgreSQL effettua la connessione effettiva al database: si verifica che l'url di connessione sia gestibile ed appropriato tramite il metodo acceptsurl(..); se non è stato specificato un timeout di login viene tentata la connessione direttamente nel thread chiamante (metodo makeconnection(..)); se è stato specificato un timeout di login viene creato un nuovo thread (ConnectionThread), che cercherà di effettuare la connessione (metodo run()) mentre il thread chiamante resterà in attesa per un tempo pari al timeout specificato (metodo getresult(..)). 114 di 182

115 connect(..) public java.sql.connection connect(string url, Properties info) public java.sql.connection connect(string url, Properties info) throws SQLException { throws SQLException { try { // se non ho nessun timeout tento la connessione try { // se non ho nessun timeout tento la connessione // direttamente (opzione di default) // direttamente (opzione di default) long timeout = timeout(props); long timeout = timeout(props); if (timeout <= 0) if (timeout <= 0) return makeconnection(url, props); return makeconnection(url, props); // tento la connessione tramite un altro thread // tento la connessione tramite un altro thread ConnectThread ct = new ConnectThread(url, props); ConnectThread ct = new ConnectThread(url, props); new Thread(ct, new Thread(ct, "PostgreSQL JDBC driver connection thread").start(); "PostgreSQL JDBC driver connection thread").start(); return ct.getresult(timeout); return ct.getresult(timeout); } catch (PSQLException ex1) { } catch (PSQLException ex1) { throw ex1; throw ex1; } catch (Exception ex2) { } catch (Exception ex2) { throw new PSQLException(...); throw new PSQLException(...); } } }} // org.postgresql.driver // org.postgresql.driver 115 di 182

116 PGStream: un oggetto magico PGStream rappresenta un wrapper attorno connessione verso il database PostgreSQL. ad una Esso contiene un riferimento ad un oggetto java.net.socket che rappresenta la connessione al database e agli stream per la lettura e la scrittura dei dati su tale socket (sottoclassi specifiche di OutpuStream e InputStream). PGStream mette a disposizione dei metodi di utilità per la scrittura/lettura di byte, interi (2,4 byte), char, stringhe, etc. che vengono usati per l'invio di informazioni secondo il protocollo di comunicazione V2 o V di 182

117 Interfacce particolari QueryExecutor: gestisce i messaggi specifici di una versione di protocollo (es. V3) per l'esecuzione di query. Una implmentazione è ad esempio org.postgresql.core.v3.queryexecutorimpl. ResultHandler: gestisce la costruzione progressiva di ResultSet (aggiunge una tupla man mano che viene ricevuta dalla rete), warning ed errori. SimpleQuery: gestione dei dati di una query singola. 117 di 182

118 Comunicazione FrontEnd-BackEnd La comunicazione fra il lato applicativo (FrontEnd driver) e il server (BackEnd) avviene tramite l'uso di un protocollo a scambio di messaggi. Il protocollo, giunto alla sua terza revisione (PostgreSQL >= 7.4) viene comunemente denominato protocollo V di 182

119 Protocollo V3: formato dei messaggi Un messaggio è un pacchetto contenente diversi byte rappresentati l'informazione. message_type (1 byte) length (4 bytes) content (length 4 bytes) il primo byte del messaggio identifica il tipo del messaggio stesso i successivi quattro byte specificano la lunghezza del messaggio stesso (incluso il dato di lunghezza stesso) i rimanenti byte rappresentano contenuto del messaggio il 119 di 182

120 PreparedStatement vs Portal La fase di parse genera un PreparedStatement, ossia un oggetto che rappresenta l'interpretazione lessicale di una query. Tale oggetto subirà poi il bind dei parametri venendo promosso in un Portal, un oggetto pronto ad eseguire la query. Sostanzialmente un Portal è un handle per una query pronta da eseguire o che sta eseguendo, una sorta di cursore (che funziona anche per query non SELECT). Un portale puo' essere identificato da un nome, oppure rimanere unnamed se si usa il portale di default. 120 di 182

121 Protocollo V3: Simple & Extended Query Il protocollo prevede due modalità principali di funzionamento: Simple Query: viene inviato un messaggio con la query e questa viene immediatamente eseguita; i risultati vengono poi inviati al frontend. Extended Query: viene inviata la query ma non viene eseguita immediatamente. In una fase successiva si fa il bind dei parametri della query, si esegue la query e si inviano i risultati al frontend. Simple Query : Statement = Extended Query : PreparedStatement 121 di 182

122 Simple Query BackEnd FrontEnd Query contiene la string SQL della query da eseguire RowDescription indica il layout delle colonne ritornate dalla query RowData dati di una singola riga RowData RowData ReadyForQuery indica che il backend è pronto ad accettare una nuova query 122 di 182

123 Extended Query BackEnd FrontEnd Parse (stringa SQL, [nome prepared statement, nome portale]) ParseComplete Bind (lista parametri, [nome prepared statement, nome portale]) BindComplete Execute ([nome portale]) RowData dati di una singola riga RowData RowData Sync sincronizzazione per errori ReadyForQuery il backend è pronto 123 di 182

124 Query: overview Viene creato un oggetto Statement dal Connection corrente. Tipicamente si passa attraverso AbstractJdbc2Connection, che richiama il tipo di connessione corretto (es. Jdbc4Connection). Il metodo executequery(..) viene sempre richiamato su AbstractJdbc2Statement, che mediante QueryExecutor ottiene un oggetto SimpleQuery che implementa il protocollo di comunicazione FrontEnd e BackEnd opportuno (es. v3). 124 di 182

125 Query: overview Il metodo execute(..) di AbstractJdbc2Statement accetta l'oggetto query da eseguire e richiama il metodo execute(..) sul QueryExecutor. Al metodo viene anche passato un oggetto ResultHandler che si occupa di gestire risultati (ResultSet), errori e warning. Il QueryExecutor invia i messaggi necessari al server, in particolare tramite il metodo sendquery(..) e sendonequery(..) invia la query da eseguire in formato testuale. 125 di 182

126 Query: overview Il QueryExecutor processa la risposta del server tramite processresult(..). Questo metodo utilizza l'oggetto PGStream per leggere i messaggi in arrivo dal server. Viene usato un meccanismo ad eventi: a seconda del messaggio letto viene richiamato un metodo opportuno sul ResultHandler. In questo modo l'handler può, ad esempio, memorizzare le tuple man mano che vengono lette. Si richiede al ResultHandler di restituire il ResultSet. Questo viene ritornato indietro lungo lo stack fino al lato applicativo. 126 di 182

127 Creazione di uno Statement public java.sql.statement createstatement() throws SQLException { public java.sql.statement createstatement() throws SQLException { // crea uno statement per un Resultset classico // crea uno statement per un Resultset classico return createstatement(java.sql.resultset.type_forward_only, return createstatement(java.sql.resultset.type_forward_only, java.sql.resultset.concur_read_only); java.sql.resultset.concur_read_only); }} // org.postgresql.jdbc2.abstractjdbc2connection // org.postgresql.jdbc2.abstractjdbc2connection public java.sql.statement createstatement(int resultsettype, public java.sql.statement createstatement(int resultsettype, int resultsetconcurrency, int resultsetholdability) int resultsetconcurrency, int resultsetholdability) throws SQLException { throws SQLException { // creazione di uno statement di livello 4 // creazione di uno statement di livello 4 Jdbc4Statement s = new Jdbc4Statement(this, resultsettype, Jdbc4Statement s = new Jdbc4Statement(this, resultsettype, resultsetconcurrency, resultsetholdability); resultsetconcurrency, resultsetholdability); s.setpreparethreshold(getpreparethreshold()); s.setpreparethreshold(getpreparethreshold()); return s; return s; }} // org.postgresql.jdbc4.jdbc4connection // org.postgresql.jdbc4.jdbc4connection La creazione di uno Statement implica ancora una volta il passaggio fra le classi dei vari livelli JDBC. In particolare si parte dal livello 2 (il minimo) e si arriva fino al livello 4 creando un Jdbc4Statement. 127 di 182

128 Esecuzione di una query public ResultSet executequery(string p_sql) throws SQLException { public ResultSet executequery(string p_sql) throws SQLException { // se ho una query preprata (PreparedStament) non processare // se ho una query preprata (PreparedStament) non processare // un'altra query SQL (p_sql) // un'altra query SQL (p_sql) if (preparedquery!= null) if (preparedquery!= null) throw new PSQLException(...); throw new PSQLException(...); // eseguo la query specificata // eseguo la query specificata if (!executewithflags(p_sql, 0)) if (!executewithflags(p_sql, 0)) throw new PSQLException(...); throw new PSQLException(...); // sono stati ritornati troppi result set in una sola volta // sono stati ritornati troppi result set in una sola volta if (result.getnext()!= null) if (result.getnext()!= null) throw new PSQLException(...); throw new PSQLException(...); return (ResultSet)result.getResultSet(); return (ResultSet)result.getResultSet(); }} // org.postgresql.jdbc2.abstractjdbc2statement // org.postgresql.jdbc2.abstractjdbc2statement Il metodo fondamentale per l'esecuzione di una query è executewithflags. Mediante tale metodo viene creato un oggetto SimpleQuery che si occuperà dello scambio di messaggi con il backend per il protocollo relativo. 128 di 182

129 Esecuzione di una query public boolean executewithflags(string p_sql, int flags) public boolean executewithflags(string p_sql, int flags) throws SQLException { throws SQLException { // controlla se lo statement è chiuso (nel caso solleva // controlla se lo statement è chiuso (nel caso solleva // una eccezione) // una eccezione) checkclosed(); checkclosed(); // effettua alcune sostituzione nella query (es. escaping) // effettua alcune sostituzione nella query (es. escaping) p_sql = replaceprocessing(p_sql); p_sql = replaceprocessing(p_sql); Query simplequery = Query simplequery = connection.getqueryexecutor().createsimplequery(p_sql); connection.getqueryexecutor().createsimplequery(p_sql); execute(simplequery, null, QueryExecutor.QUERY_ONESHOT flags); execute(simplequery, null, QueryExecutor.QUERY_ONESHOT flags); this.lastsimplequery = simplequery; this.lastsimplequery = simplequery; // result è un tipo ResultWrapper, che contiene // result è un tipo ResultWrapper, che contiene // anche il ResultSet // anche il ResultSet return (result!= null && result.getresultset()!= null); return (result!= null && result.getresultset()!= null); }} // org.postgresql.jdbc2.abstractjdbc2statement // org.postgresql.jdbc2.abstractjdbc2statement public Query createsimplequery(string sql) { public Query createsimplequery(string sql) { return parsequery(sql, false); return parsequery(sql, false); }} // org.postgresql.core.v3.queryexecutorimpl // org.postgresql.core.v3.queryexecutorimpl 129 di 182

130 Esecuzione di una query protected void execute(query querytoexecute, protected void execute(query querytoexecute, ParameterList queryparameters, int flags) throws SQLException { ParameterList queryparameters, int flags) throws SQLException { // chiusura di query precedenti e pulizia di warning ed errori // chiusura di query precedenti e pulizia di warning ed errori // che potevano provenire da query precedenti // che potevano provenire da query precedenti StatementResultHandler handler = new StatementResultHandler(); StatementResultHandler handler = new StatementResultHandler(); result = null; result = null; connection.getqueryexecutor().execute(querytoexecute, connection.getqueryexecutor().execute(querytoexecute, queryparameters, queryparameters, handler, handler, maxrows, maxrows, fetchsize, fetchsize, flags); flags); result = firstunclosedresult = handler.getresults(); result = firstunclosedresult = handler.getresults(); }} // org.postgresql.jdbc2.abstractjdbc2statement // org.postgresql.jdbc2.abstractjdbc2statement Si prepara un handler per il risultato ed eventuali errori e si passa la query e l'handler al metodo execute(..) del QueryExecutor (la sua implementazione per il protocollo V3) affinché gestisca i messaggi. 130 di 182

131 Esecuzione di una query (lettura risultati) protected void processresults(resulthandler handler, int flags) protected void processresults(resulthandler handler, int flags) throws IOException { throws IOException { Vector tuples = new Vector(); Field[] fields = null; Vector tuples = new Vector(); Field[] fields = null; while (!endquery) { while (!endquery) { c = pgstream.receivechar(); c = pgstream.receivechar(); switch (c){ switch (c){ case 'D': // messaggio di tipo DataRow case 'D': // messaggio di tipo DataRow Object tuple = null; Object tuple = null; try { try { tuple = pgstream.receivetuplev3(); tuple = pgstream.receivetuplev3(); } catch(outofmemoryerror oome) {... } } catch(outofmemoryerror oome) {... } if (!noresults) if (!noresults) tuples.addelement(tuple); tuples.addelement(tuple); break; break; // org.postgresql.core.v3.queryexecutorimpl // org.postgresql.core.v3.queryexecutorimpl 131 di 182

132 Esecuzione di una query (lettura risultati) case 'C': // command status (fine esecuzione execute) case 'C': // command status (fine esecuzione execute) String status = receivecommandstatus(); String status = receivecommandstatus(); if (fields!= null tuples!= null) { if (fields!= null tuples!= null) { handler.handleresultrows(currentquery, fields, tuples, null); handler.handleresultrows(currentquery, fields, tuples, null); fields = null; tuples = null; fields = null; tuples = null; } } else else interpretcommandstatus(status, handler); interpretcommandstatus(status, handler); break; break; case 'Z': // ready for query case 'Z': // ready for query receiverfq(); receiverfq(); endquery = true; // termina il ciclo while endquery = true; // termina il ciclo while // pulizia degli oggetti in memoria e delle code // pulizia degli oggetti in memoria e delle code break; break; } } } } }} // org.postgresql.core.v3.queryexecutorimpl // org.postgresql.core.v3.queryexecutorimpl 132 di 182

133 Query: traffico di rete Analizzando il traffico di rete con uno sniffer è possibile vedere i singoli messaggi inviati da e per il server. Nell'esempio qui sopra si nota il messaggio di Parse, con la query inviata, seguito da vari messaggi uno dei quali Execute. 133 di 182

134 Query: traffico di rete In questo caso si vede il messaggio RowDescription che precede una serie di messaggi DataRow, ciascuno con indicazione del numero, lunghezza e valore delle colonne. 134 di 182

135 Query: traffico di rete Messaggio Parse contenente la query e il nome dello statement di riferimento sul server (null). Il server invia un RowDescription e di seguito tutte le righe tramite una serie di DataRow. Il server invia i messaggi di chiusura, fra i quali ReadyForQuery. 135 di 182

136 Esecuzione di una query parametrica statement2.setint(1, corsopk); statement2.setint(1, corsopk); // lato applicativo // lato applicativo La fase di bind in memoria prevede che il parametro sia associato alla sua posiziona nella query (index), al suo valore (rappresentato come stringa) e al suo tipo (OID) affinché il BackEnd possa capire come trattare il dato stesso. I parametri sono contenuti in oggetti che implementano ParameterList a seconda del protocollo utilizzato (ad es. V3ParameterList). public void setint(int parameterindex, int x) throws SQLException { public void setint(int parameterindex, int x) throws SQLException { checkclosed(); checkclosed(); bindliteral(parameterindex, Integer.toString(x), Oid.INT4); bindliteral(parameterindex, Integer.toString(x), Oid.INT4); }} private void bindliteral(int paramindex,string s,int oid) private void bindliteral(int paramindex,string s,int oid) throws SQLException { throws SQLException { if(adjustindex) if(adjustindex) paramindex ; paramindex ; // registro il parametro in un contenitore V3ParameterList // registro il parametro in un contenitore V3ParameterList preparedparameters.setliteralparameter(paramindex, s, oid); preparedparameters.setliteralparameter(paramindex, s, oid); } // org.postgresql.jdbc2.abstractjdbc2statement } // org.postgresql.jdbc2.abstractjdbc2statement 136 di 182

137 Esecuzione di una query parametrica Il metodo executequery(), invocato dopo il bind dei parametri, richiama il metodo executewithflags(..) già visto in precedenza e usato anche per query non parametriche. Ripercorrendo lo stack di chiamata si giunge a QueryExecutor.execute(..) che questa volta ha impostato i parametri della query. Da qui si passa poi a QueryExecutor.sendOneQuery(..) che provvede a sostituire ad ogni parametro (indicato con?) un $n (con n valore della posizione partendo da 1). In coda alla query compare poi l'array degli OID dei tipi dei parametri. public java.sql.resultset executequery() throws SQLException { public java.sql.resultset executequery() throws SQLException { if (!executewithflags(0)) if (!executewithflags(0)) throw new PSQLException(...); throw new PSQLException(...); if (result.getnext()!= null) if (result.getnext()!= null) throw new PSQLException(...); throw new PSQLException(...); return (ResultSet) result.getresultset(); return (ResultSet) result.getresultset(); } // org.postgresql.jdbc2.abstractjdbc2statement } // org.postgresql.jdbc2.abstractjdbc2statement FE=> Parse(stmt=null,query="SELECT cognome, nome FE=> Parse(stmt=null,query="SELECT cognome, nome FROM partecipante WHERE corsopk=$1",oids={23}) FROM partecipante WHERE corsopk=$1",oids={23}) 137 di 182

138 Esecuzione di una query parametrica private void sendbind(simplequery query, SimpleParameterList params, private void sendbind(simplequery query, SimpleParameterList params, Portal portal) throws IOException { Portal portal) throws IOException { // informazioni su portale e statement (se esistono) // informazioni su portale e statement (se esistono) String statementname = query.getstatementname(); String statementname = query.getstatementname(); byte[] encodedstatementname = query.getencodedstatementname(); byte[] encodedstatementname = query.getencodedstatementname(); byte[] encodedportalname = (portal == null? null : byte[] encodedportalname = (portal == null? null : portal.getencodedportalname()); portal.getencodedportalname()); pgstream.sendchar('b'); pgstream.sendchar('b'); // messaggio Bind // messaggio Bind pgstream.sendinteger4((int)encodedsize); // dimensione messaggio pgstream.sendinteger4((int)encodedsize); // dimensione messaggio if (encodedportalname!= null) // eventuale portale if (encodedportalname!= null) // eventuale portale pgstream.send(encodedportalname); pgstream.send(encodedportalname); pgstream.sendchar(0); pgstream.sendchar(0); if (encodedstatementname!= null) if (encodedstatementname!= null) pgstream.send(encodedstatementname); pgstream.send(encodedstatementname); // eventuale statement // eventuale statement pgstream.sendchar(0); pgstream.sendchar(0); // org.postgresql.core.v3.queryexecutorimpl // org.postgresql.core.v3.queryexecutorimpl 138 di 182

139 Esecuzione di una query parametrica // invio tipo e numero dei parametri // invio tipo e numero dei parametri for (int i = 1; i <= params.getparametercount(); ++i) for (int i = 1; i <= params.getparametercount(); ++i) pgstream.sendinteger2(params.isbinary(i)? 1 : 0); pgstream.sendinteger2(params.isbinary(i)? 1 : 0); pgstream.sendinteger2(params.getparametercount()); pgstream.sendinteger2(params.getparametercount()); for (int i = 1; i <= params.getparametercount(); ++i) { for (int i = 1; i <= params.getparametercount(); ++i) { if (params.isnull(i)) if (params.isnull(i)) pgstream.sendinteger4( 1); // dimensione 1 => NULL pgstream.sendinteger4( 1); // dimensione 1 => NULL else { else { // dimensione del parametro // dimensione del parametro pgstream.sendinteger4(params.getv3length(i)); pgstream.sendinteger4(params.getv3length(i)); try{ // valore del parametro try{ // valore del parametro params.writev3value(i, pgstream); params.writev3value(i, pgstream); }catch (PGBindException be) { }catch (PGBindException be) { bindexception = be; bindexception = be; } } } } } } } // org.postgresql.core.v3.queryexecutorimpl } // org.postgresql.core.v3.queryexecutorimpl 139 di 182

140 Esecuzione di INSERT/UPDATE I passi fondamentali sono simili a quanto visto in precedenza: si deve ottenere (AbstractJdbc2Connection) (AbstractJdbc2Statement); dall'oggetto uno Connection Statement si richiede allo Statement (AbstractJdbc2Statement) di eseguire la modifica mediante il metodo JDBC executeupdate(string sql); si ottiene come valore di ritorno il numero di record modificati nella base di dati (command status) Il command status viene interpretato letteralmente, ossia dalla stringa di command status inviata dal BackEnd si estraggono i valori ritornati dal server. 140 di 182

141 Esecuzione di un INSERT/UPDATE public int executeupdate(string p_sql) throws SQLException { public int executeupdate(string p_sql) throws SQLException { // eseguo la query tramite il QueryExecutor // eseguo la query tramite il QueryExecutor // non mi aspetto risultati (QUERY_NO_RESULTS) // non mi aspetto risultati (QUERY_NO_RESULTS) if (executewithflags(p_sql, QueryExecutor.QUERY_NO_RESULTS)) if (executewithflags(p_sql, QueryExecutor.QUERY_NO_RESULTS)) // non dovrei avere alcun risultato // non dovrei avere alcun risultato throw new PSQLException(...); throw new PSQLException(...); // restituisco il numero di record aggiornati/inseriti // restituisco il numero di record aggiornati/inseriti return getupdatecount(); return getupdatecount(); } // org.postgresql.jdbc2.asbtractjdbc2statement } // org.postgresql.jdbc2.asbtractjdbc2statement public boolean executewithflags(string p_sql, int flags) public boolean executewithflags(string p_sql, int flags) throws SQLException { throws SQLException { Query simplequery = Query simplequery = connection.getqueryexecutor().createsimplequery(p_sql); connection.getqueryexecutor().createsimplequery(p_sql); execute(simplequery, null, QueryExecutor.QUERY_ONESHOT flags); execute(simplequery, null, QueryExecutor.QUERY_ONESHOT flags); this.lastsimplequery = simplequery; this.lastsimplequery = simplequery; return (result!= null && result.getresultset()!= null); return (result!= null && result.getresultset()!= null); }} // org.postgresql.jdbc2.asbtractjdbc2statement // org.postgresql.jdbc2.asbtractjdbc2statement 141 di 182

142 Esecuzione di un INSERT/UPDATE protected void processresults(resulthandler handler, int flags) protected void processresults(resulthandler handler, int flags) throws IOException { throws IOException { case 'C': // Command Status (end of Execute) case 'C': // Command Status (end of Execute) // ottiene la stringa risultato dell'esecuzione della query // ottiene la stringa risultato dell'esecuzione della query // ad esempio INSERT 0 1 oppure UPDATE 1 // ad esempio INSERT 0 1 oppure UPDATE 1 String status = receivecommandstatus(); String status = receivecommandstatus(); if (fields!= null tuples!= null){ if (fields!= null tuples!= null){ // qui c'e' un ResultSet, quindi una select // qui c'e' un ResultSet, quindi una select handler.handleresultrows(currentquery, fields, tuples, null); handler.handleresultrows(currentquery, fields, tuples, null); fields = null; tuples = null; fields = null; tuples = null; } } else { else { // qui non c'e' ResultSet, quindi una scrittura sul DB // qui non c'e' ResultSet, quindi una scrittura sul DB interpretcommandstatus(status, handler); interpretcommandstatus(status, handler); } } } // org.postgresql.core.v3.queryexecutorimpl } // org.postgresql.core.v3.queryexecutorimpl 142 di 182

143 Pl/Java 143 di 182

144 Installazione di Pl/Java Pljava si basa su un modulo del kernel denominato pljava.so; la versione base è compilata per architettura 32 bit e verso PostgreSQL 8.3. Per una corretta installazione su piattaforme e database differenti occorre: usare un JDK fra la versione 4 e 5 (non la 6 perché cambiano le API JDBC); installare gli header per lo sviluppo di PostgreSQL della versione corrente (ad esempio postgresql server dev 8.4); scaricare tramite CVS l'ultima versione dei sorgenti di Pl/Java; verificare che JAVA_HOME e il PATH puntino al compilatore Java corretto; lanciare la compilazione con il comando make. 144 di 182

145 Installazione di Pl/Java Occorre poi apportare alcune modifiche a postgresql.conf affinché il server-cluster postmaster possa caricare l'estensione Java: dynamic_library_path = '$libdir:/sviluppo/java/pljava/org.postgresql.pljava/build/objs' custom_variable_classes = 'pljava' pljava.classpath='/sviluppo/java/pljava/org.postgresql.pljava/build /pljava.jar' 145 di 182

146 Introduzione a Pl/Java Pl/Java è una estensione di PostgreSQL per supportare il linguaggio Java come linguaggio interno. Pl/Java è simile, concettualmente, ad altri Pl/xxx come ad esempio Pl/Perl. La differenza principale con altri linguaggi è che, essendo Java compilato, non è possibile scrivere direttamente codice Java all'interno del server, bensì si deve istruire il server per richiamare del codice Java in formato bytecode. In altre parole usare Pl/Java significa sempre: Scrivere del codice Java. Scrivere del codice SQL per richiamare Java. 146 di 182

147 JNI? Il backend PostgreSQL non è scritto in Java! Occorre quindi trovare un modo per far dialogare un pezzo di codice Java con il backend. Ci sono due soluzioni possibili: RPC JNI Pl/Java si basa su JNI per svariate ragioni, principalmente: Piu' semplice ed efficiente Il codice Java risiede sul server, quindi è locale al backend (non c'è necessità di usare chiamate remote) 147 di 182

148 1 backend = 1 JVM? // backend.c static void initializejavavm(void){... jstat = JNI_createVM(&s_javaVM, &vm_args);... } Nel file backend.c, che inizializza il collegamento fra il backend vero e proprio e Java, si ha che per ogni connessione viene avviata una JVM tramite JNI. In sostanza si ha una JVM per ogni connessione utente. Ciò è coerente con il design di PostgreSQL che prevede un processo (backend appunto) per ogni connessione utente, inoltre garantisce la protezione dello spazio utente tramite l'astrazione dei processi e infine consente di gestire la priorità dei processi stessi tramite gli strumenti del sistema operativo (ps, nice,...). 148 di 182

149 Installazione di Pl/Java PlJava viene fornito con uno strumento (Java) per l'installazione del supporto Java presso un determinato database: deploy.jar. Occorre eseguire questo programma Java (che richiede la presenza del driver JDBC PostgreSQL) per installare il supporto dinamico a Java nel database: java org.postgresql.pljava.deploy.deployer install database hrpmdb user postgres password postgres Il programma provvede a creare le funzioni handler e lo schema speciale sqlj nel database. 149 di 182

150 Vedere cosa succede dietro le quinte E' bene abilitare il livello di log_min_messages a debug3 per ottenere un po' di informazioni circa l'utilizzo di Java nel server. Nei log si troveranno messaggi circa la creazione dell'istanza della JVM e il caricamento delle classi :55:03 CEST DEBUG: find_in_dynamic_libpath: trying "/usr/lib/postgresql/8.4/lib/pljava" :55:03 CEST DEBUG: find_in_dynamic_libpath: trying "/sviluppo/java/pljava/org.postgresql.pljava/build/objs/pljava" :55:03 CEST DEBUG: find_in_dynamic_libpath: trying "/usr/lib/postgresql/8.4/lib/pljava.so" :55:03 CEST DEBUG: find_in_dynamic_libpath: trying "/sviluppo/java/pljava/org.postgresql.pljava/build/objs/pljava.so" :55:03 CEST DEBUG: Using integer_datetimes :55:03 CEST DEBUG: Added JVM option string " Djava.class.path=/sviluppo/java/pljava/org.postgresql.pljava/build" :55:03 CEST DEBUG: Added JVM option string " Dsqlj.defaultconnection=jdbc:default:connection" :55:03 CEST DEBUG: Added JVM option string "vfprintf" :55:03 CEST DEBUG: Added JVM option string " Xrs" :55:03 CEST DEBUG: Creating JavaVM :55:03 CEST DEBUG: JavaVM created :55:03 CEST DEBUG: Getting Backend class pljava.jar 150 di 182

151 Un primo esempio di funzione CREATE FUNCTION getsysprop(varchar) RETURNS VARCHAR AS 'java.lang.system.getproperty' LANGUAGE java; 151 di 182

152 Scrivere funzioni PL/Java Ogni metodo invocabile in PostgreSQL deve essere un metodo statico (i parametri devono corrispondere a quelli passati alla funzione SQL). Ogni funzione Java deve essere invocata tramite una funzione SQL. Le classi devono essere contenute in un file jar caricato e impostato nel classpath del database. Il classpath viene amministratori. gestito solo dagli utenti ATTENZIONE: se vengono riportate eccezioni di sicurezza significa che la classe è presente nel classpath del processo postmaster e quindi viene caricata senza passare dal motore database! 152 di 182

153 Un secondo esempio di funzione 153 di 182

154 Parametri e tipi di ritorno: un esempio 154 di 182

155 NULL vs null Il tipo NULL del linguaggio SQL viene tradotto nel tipo null di Java. Però per SQL è lecito avere NULL anche dove c'è uno scalare, mentre per Java no! Di conseguenza le funzioni che lavorino con scalari (in ingresso/uscita) e che debbano gestire tipi NULL (SQL) devono usare le classi wrapper. 155 di 182

156 Funzioni che restituiscono un SETOF Pl/Java richiede che una funzione che ritorna un SETOF (lato SQL) restituisca un Iterator (lato Java). Non verranno accettati altri tipi di ritorno! E' comunque possibile usare un qualunque tipo di dato/struttura che implementi l'interfaccia Iterator. 156 di 182

157 Creazione di Trigger Il codice Java dipende dalle librerie Pl/Java Ogni funzione trigger non restituisce nulla (void) e accetta come parametro un oggetto TriggerData con le informazioni sull'invocazione del Trigger. Tramite TriggerData è possibile selezionare il result set new oppure old e su questi agire (old è in sola lettura). 157 di 182

158 Esempio di Trigger Si vuole creare un trigger che modifichi una stringa di testo con le metainformazioni sul trigger stesso. 158 di 182

159 Esempio di Trigger 159 di 182

160 Esempio piu' complesso di Trigger Si supponga di voler tenere traccia del numero globali di invocazioni della funzione trigger, del numero di update di una riga e di impedire le cancellazioni delle righe che sono state aggiornate un numero pari di volte. 160 di 182

161 Codice della funzione Trigger public class Trigger { public static int globalcounter = 0; public static void triggerjavamethod( TriggerData triggerdata ) throws SQLException{ // e' un trigger per update? if( triggerdata.isfiredbyupdate() ){ // prelevo il result set nuovo ResultSet newrs = triggerdata.getnew(); // prelevo il vecchio result set ResultSet oldrs = triggerdata.getold(); // inserisco il contatore globale newrs.updateint("global_counter", ++globalcounter); // incremento il contatore di update newrs.updateint("update_counter", oldrs.getint("update_counter") + 1); } else if( triggerdata.isfiredbydelete() ){ ResultSet oldrs = triggerdata.getold(); if( ( oldrs.getint("update_counter") % 2 ) == 0 ) throw new TriggerException(triggerData, "Tupla non.."); } } Non esiste ancora un metodo efficace per gestire l'abort di un trigger! Lanciare una eccezione non funziona appieno: blocca la transazione nel backend! 161 di 182

162 Esecuzione del Trigger 162 di 182

163 Maneggiare tipi complessi I tipi complessi devono essere trattati tramite un ResultSet aggiornabile. Si rinuncia al paradigma OOP per passare ad un paradigma in stile record-based. E' comodo usare un ResultSetGenerator: La funzione (lato SQL) richiama un metodo (lato Java) statico che restituisce un oggetto che implementa l'interfaccia ResultSetProvider. ResultSetProvider contiene due metodi: assignrowvalues(..) che permette l'update di una cella (riga/colonna) nel ResultSet e close() usato per rilasciare le risorse. ResultSetProvider.assignRowValues(..) restituisce false se non ci sono altre righe da processare, true se ancora una riga deve essere inserita nel ResultSet. 163 di 182

164 Maneggiare tipi complessi: generare delle tuple public class RowGenerator implements ResultSetProvider { private static int NUM_ROWS = 10; private static int NUM_COLS = 5; public boolean assignrowvalues(resultset rs, int rownumber) throws SQLException { if( rownumber <= NUM_ROWS ){ for( int j = 1; j <= NUM_COLS; j++ ) rs.updatestring(j, "Riga " + rownumber + " Colonna " + j); return true; } else return false; } public void close() throws SQLException { System.out.println("Chiusura del row set provider"); } public static ResultSetProvider generaterows(){ return new RowGenerator(); } } 164 di 182

165 Maneggiare tipi complessi: invocazioni SQL 165 di 182

166 JDBC & Pl/Java =~ SQL MED E' possibile chiamare JDBC da Pl/Java, in modo da poter interrogare in modo riflessivo il database al quale si è connessi. In questo modo si possono ottenere (e restituire) i dati appartenenti ad altre tabelle/relazioni. 166 di 182

167 JDBC & Pl/Java =~ SQL MED public class RowGenerator implements ResultSetHandle { private String databasename; private String username; private String password; private String tablename; public RowGenerator(String database, String username, String password, String table ){ this.databasename = database; this.username = username; this.password = password; this.tablename = table; } // funzione usata lato SQL public static ResultSetHandle generaterows(string database, String username, String password, String table){ return new RowGenerator( database, username, password, table ); } 167 di 182

168 JDBC & Pl/Java = SQL MED // funzione usata per ottenere le tuple public ResultSet getresultset() throws SQLException { org.postgresql.driver driver = new org.postgresql.driver(); Connection connection = DriverManager.getConnection( this.databasename, this.username, this.password ); Statement statement = connection.createstatement(); return statement.executequery(" SELECT * FROM "+ this.tablename ); } } Se la funzione viene creata come linguaggio untrusted allora è possibile usare la connessione verso ogni database, e quindi implementare un SQL MED completo. ATTENZIONE: i driver devono trovarsi nel classpath! 168 di 182

169 Utilizzo dei SavePoint public static void executeinsert(int counter) throws SQLException{ Connection connection = DriverManager.getConnection("jdbc:default:connection"); Statement statement = connection.createstatement(); Savepoint save = null; // effettuo 10 inserimenti for( int i = 0; i < counter; i++ ){ statement.execute("insert INTO java_table(nome) VALUES('inserimento " + i + "')"); if( i >= (counter / 2) && save == null ) save = connection.setsavepoint(); } // rollback connection.rollback( save ); } 169 di 182

170 SavePoint: risultato 170 di 182

171 Listener private static Logger logger = Logger.getAnonymousLogger(); public static void executeinsert(int counter) throws SQLException{ Connection connection = DriverManager.getConnection("jdbc:default:connection"); Session session = SessionManager.current(); session.addsavepointlistener( new SavepointListener() { public void onstart(session arg0, Savepoint arg1, Savepoint arg2) throws SQLException { logger.info("savepoint START " + arg0 + " savepoints " + arg1 + " " + arg2); } public void oncommit(session arg0, Savepoint arg1, Savepoint arg2) throws SQLException { logger.info("savepoint COMMIT" + arg0 + " savepoints " + arg1 + " " + arg2); } public void onabort(session arg0, Savepoint arg1, Savepoint arg2) throws SQLException { logger.info("savepoint ABORT " + arg0 + " savepoints " + arg1 + " " + arg2); } }); 171 di 182

172 Listener E' possibile agganciare dei listener per le transazioni (TransactionListener) e per la gestione dei SavePoint (sotto-transazioni) (SavePointListener). 172 di 182

173 JDBC & Pl/Java =~ SQL MED public class RowGenerator implements ResultSetHandle { private String databasename; private String username; private String password; private String tablename; public RowGenerator(String database, String username, String password, String table ){ this.databasename = database; this.username = username; this.password = password; this.tablename = table; } public static ResultSetHandle generaterows(string database, String username, String password, String table){ return new RowGenerator( database, username, password, table ); } public ResultSet getresultset() throws SQLException { Connection connection = DriverManager.getConnection( this.databasename, this.username, this.password ); Statement statement = connection.createstatement(); return statement.executequery(" SELECT * FROM "+ this.tablename ); } } 173 di 182

174 Singleton e PooledObjects Pl/Java consente la gestione di oggetti in un pool, ovvero un recipiente di oggetti che possono essere riciclati per scopi futuri. In un certo senso questo aiuta nel paradigma dei singleton. Ogni oggetto che deve essere gestibile da un pool deve implementare l'interfaccia PooledObject e implementare i metodi per la attivazione e disattivazione. Il costruttore dell'oggetto deve accettare il pool di appartenenza (ObjectPool) sul quale puo' operare. 174 di 182

175 Esempio di PooledObject public class Pooled implements PooledObject{ private long creationtimemillis; private ObjectPool mypool; public Pooled( ObjectPool mypool ){ super(); this.creationtimemillis = Calendar.getInstance().getTimeInMillis(); this.mypool = mypool; } public void activate() throws SQLException { System.out.println("Oggetto <" + creationtimemillis + "> attivato!"); } public void passivate() throws SQLException { System.out.println("Oggetto <" + creationtimemillis + "> disattivato!"); } 175 di 182

176 Esempio di PooledObject public void remove() { System.out.println("Oggetto <" + creationtimemillis + "> rimosso!"); } public static void createpooledobject() throws SQLException{ // ottengo la sessione corrente Session session = SessionManager.current(); // ottengo il pool di oggetti ObjectPool pool = session.getobjectpool( Pooled.class ); // ottengo una istanza dal pool Pooled mypooled = (Pooled) pool.activateinstance(); // ci faccio qualcosa... // poi lo reinserisco nel pool pool.passivateinstance(mypooled); } } 176 di 182

177 Esempio di PooledObject Se si invoca ripetutamente la funzione di generazione dell'oggetto si nota che è sempre lo stesso oggetto ad essere usato. Se l'oggetto non viene reinserito nel pool, allora un nuovo viene creato e usato. 177 di 182

178 Multithreading Problema: Java è un linguaggio che supporta il multithreading, ma il backend PostgreSQL è un singolo processo senza supporto ai thread. Il supporto al multithreading di Java deve essere comunque garantito! Se si pensa al backend come ad un ennesimo thread, allora tutti i thread (Java e di backend) devono sincronizzarsi in modo coerente: si utilizza un singolo lock! Viene definito un oggetto particolare, Backend.THREADLOCK sul quale tutti si sincronizzano. il 178 di 182

179 Backend.THREADLOCK 179 di 182

JDBC versione base. Le classi/interfacce principali di JDBC

JDBC versione base. Le classi/interfacce principali di JDBC JDBC versione base Java Database Connectivity è il package Java per l accesso a database relazionali il package contiene interfacce e classi astratte uno dei pregi è la completa indipendenza del codice

Dettagli

JDBC di base. Le classi/interfacce principali di JDBC

JDBC di base. Le classi/interfacce principali di JDBC JDBC di base Java Database Connectivity è il package Java per l accesso a database relazionali il package contiene interfacce e classi astratte completa indipendenza del codice dal tipo di database o di

Dettagli

JDBC: Introduzione. Java Database Connectivity (JDBC): parte 1. Schema dei legami tra le classi principali. Principali classi/interfacce di JDBC

JDBC: Introduzione. Java Database Connectivity (JDBC): parte 1. Schema dei legami tra le classi principali. Principali classi/interfacce di JDBC JDBC: Introduzione Java Database Connectivity (JDBC): parte 1 Gianluca Moro DEIS - Università di Bologna gmoro@deis.unibo.it Java Database Connectivity è il package Java per l accesso a database relazionali

Dettagli

Non si deve fare ALCUN riferimento alla parte specifica di JDBC.

Non si deve fare ALCUN riferimento alla parte specifica di JDBC. Un applicazione per la quale sia fondamentale l indipendenza dal Database può essere scritta in Java usando le specifiche. (Package java.sql) Non devono essere usate chiamate specifiche del database: Si

Dettagli

JDBC. A. Bechini 2004. Accesso a DataD con Java

JDBC. A. Bechini 2004. Accesso a DataD con Java JDBC Accesso a DataD atabase ase con Java Utilizzo di DB da applicazioni esterne Un DB contiene e gestisce dati, importanti per varie operazioni supportate da applicazioni software Come può un applicazione

Dettagli

Laboratorio di reti II: Gestione di database lato server

Laboratorio di reti II: Gestione di database lato server Laboratorio di reti II: Gestione di database lato server Stefano Brocchi brocchi@dsi.unifi.it 23 marzo, 2009 Stefano Brocchi Laboratorio di reti II: Database 23 marzo, 2009 1 / 32 Uso di database lato

Dettagli

JDBC. Dispense per il corso di Ingegneria del Web

JDBC. Dispense per il corso di Ingegneria del Web JDBC Dispense per il corso di Ingegneria del Web Revisione 05/11 Giuseppe Della Penna (giuseppe.dellapenna@di.univaq.it) Dipartimento di Informatica Università degli studi dell'aquila Java Database Connectivity:

Dettagli

Sviluppo Applicazioni Mobile Lezione 12 JDBC. Dr. Paolo Casoto, Ph.D - 2012

Sviluppo Applicazioni Mobile Lezione 12 JDBC. Dr. Paolo Casoto, Ph.D - 2012 + Sviluppo Applicazioni Mobile Lezione 12 JDBC + Cosa vediamo nella lezione di oggi Oggi analizzeremo insieme una specifica tecnologia Java per l accesso e la manipolazione di basi di dati relazionali

Dettagli

CORSO DI ALGORITMI E PROGRAMMAZIONE. JDBC Java DataBase Connectivity

CORSO DI ALGORITMI E PROGRAMMAZIONE. JDBC Java DataBase Connectivity CORSO DI ALGORITMI E PROGRAMMAZIONE JDBC Java DataBase Connectivity Anno Accademico 2002-2003 Accesso remoto al DB Istruzioni SQL Rete DataBase Utente Host client Server di DataBase Host server Accesso

Dettagli

JDBC: Java e database.

JDBC: Java e database. JDBC: Java e database. Introduzione all architettura e esempi di utilizzo 1.0 INTRODUZIONE ALL ARCHITETTURA JDBC è (anche se non ufficialmente riconosciuto da Sun) l acronimo per Java DataBase Connectivity.

Dettagli

SQL. Laboratorio di Progettazione di Basi di Dati (CdS in Informatica e TPS)

SQL. Laboratorio di Progettazione di Basi di Dati (CdS in Informatica e TPS) 1 SQL Laboratorio di Progettazione di Basi di Dati (CdS in Informatica e TPS) a.a. 2014/2015 http://www.di.uniba.it/~lisi/courses/basi-dati/bd2014-15.htm Dott.ssa Francesca A. Lisi dott.ssa Francesca A.

Dettagli

JDBC per l accesso Java a DB. Tito Flagella tito@link.it

JDBC per l accesso Java a DB. Tito Flagella tito@link.it JDBC per l accesso Java a DB Tito Flagella tito@link.it JDBC fornisce una libreria standard per l accesso a database relazionali Non è un acronimo ufficiale ma è comunemente interpretato come Java DataBase

Dettagli

PostgreSQL per programmatori

PostgreSQL per programmatori PostgreSQL per programmatori Gabriele Bartolini Flavio Casadei Della Chiesa Luca Ferrari Marco Tofanari Associazione Italiana PostgreSQL Users Group www.itpug.org Pisa, 8 Maggio 2009 1 Licenza Creative

Dettagli

JDBC Driver Manager. JDBC Architettura generale. JDBC - Tipi di dato. JDBC - Flusso applicativo. JDBC - Tipi di dato. ODBC Driver. Livello di gestione

JDBC Driver Manager. JDBC Architettura generale. JDBC - Tipi di dato. JDBC - Flusso applicativo. JDBC - Tipi di dato. ODBC Driver. Livello di gestione Interfacce DBMS in breve Corso di BD1 Ripasso comandi applicazione JDBC Manipolazione estensioni OR in JDBC Interfacce per DBMS Problema: Far accedere un applicazione ad una base di dati Soluzione: Librerie

Dettagli

Introduzione. 8- Programmazione di una base di dati attraverso JDBC ESEMPIO

Introduzione. 8- Programmazione di una base di dati attraverso JDBC ESEMPIO 8- Programmazione di una base di dati attraverso JDBC Introduzione ai differenti approcci - JDBC: Architettura e Programmazione Introduzione Nella pratica gli utenti finali accedono al contenuto di una

Dettagli

Esercitazione su JDBC

Esercitazione su JDBC Esercitazione su JDBC Basi di Dati L Ingegneria dei Processi Gestionali (Ilaria Bartolini - Roberto Cabras) come usare SQL (1) Le istruzioni SQL possono essere eseguite interattivamente Ese JDBC 2 come

Dettagli

Java: la libreria delle classi

Java: la libreria delle classi Java: la libreria delle classi Applet anatomia di un applet cenni di html La libreria JDBC per l accesso ai database il package java.sql 213 Applet Un applet è una applicazione Java che ha una forma particolare

Dettagli

SQL e applicazioni. Capitolo 8. SQL e linguaggi di programmazione. Applicazioni ed SQL: architettura. Una difficoltà importante.

SQL e applicazioni. Capitolo 8. SQL e linguaggi di programmazione. Applicazioni ed SQL: architettura. Una difficoltà importante. SQL e applicazioni Capitolo 8 Applicazioni tradizionali In applicazioni complesse, l utente non vuole eseguire comandi SQL, ma programmi, con poche scelte SQL non basta, sono necessarie altre funzionalità,

Dettagli

Programmazione Java Avanzata Spring - JDBC

Programmazione Java Avanzata Spring - JDBC Programmazione Java Avanzata Spring - JDBC Ing. Gianluca Caminiti Riferimenti Spring http://www.springsource.org/ (scaricate il reference) Beginning Spring 2 - From Novice to Professional. APress. 2008

Dettagli

Accesso a Database con JDBC

Accesso a Database con JDBC 1 Sommario Accesso a Database con JDBC Introduzione architettura generale di riferimento flusso tipico delle applicazioni ODBC/JDBC ODBC architettura il flusso generale di un applicazione ODBC JDBC architettura

Dettagli

Introduzione JDBC interfaccia java.sql driver caricare i driver

Introduzione JDBC interfaccia java.sql driver caricare i driver J D B C DISPENSE Introduzione JDBC (Java Database Connectivity) è un interfaccia completamente Java utilizzata per eseguire istruzioni SQL sui database. L'API JDBC si trova nel pacchetto java.sql; contiene

Dettagli

Tecnologia e Applicazioni Internet 2011/12

Tecnologia e Applicazioni Internet 2011/12 Tecnologia e Applicazioni Internet 2011/12 Lezione 4 - Persistenza Matteo Vaccari http://matteo.vaccari.name/ matteo.vaccari@uninsubria.it Perché usare un DB relazionale? Per l accesso concorrente ai dati

Dettagli

Indice. Java. JDBC è l interfaccia di base standard di Java ai database relaionali

Indice. Java. JDBC è l interfaccia di base standard di Java ai database relaionali Java java database connectivity -- jdbc G. Prencipe prencipe@di.unipi.it Indice JDBC: Java Data Base Connectivity connessioni a basi di dati esecuzione di statement SQL accesso ai result set JDBC: Java

Dettagli

PROVA FINALE Ingegneria del software

PROVA FINALE Ingegneria del software PROVA FINALE Ingegneria del software Ing. Jody Marca jody.marca@polimi.it Laboratorio N 4 Cos è JDBC 2 JDBC significa Java Database Connectivity Standard definito da Sun MicroSystems per connettere programmi

Dettagli

DBMS ed Applicazioni Motivazioni

DBMS ed Applicazioni Motivazioni DBMS ed Applicazioni Motivazioni Sin ora abbiamo visto SQL come linguaggio per interrogare DBMS da interfaccia interattiva Nella pratica, un efficace sfruttamento delle potenzialità dei DBMS deriva dalla

Dettagli

JDBC. Di Michele de Nittis Versione 06/08/2008 www.mdenittis.it

JDBC. Di Michele de Nittis Versione 06/08/2008 www.mdenittis.it JDBC Di Michele de Nittis Versione 06/08/2008 www.mdenittis.it JDBC...1 Introduzione...2 Caricamento dell appropriato Driver JDBC...2 Classi...3 Connection...4 Statement...5 PreparedStatement...6 ResultSet...7

Dettagli

Scheda 15 Accedere ai DataBase con JDBC

Scheda 15 Accedere ai DataBase con JDBC Scheda 15 Accedere ai DataBase con JDBC G IOVANNI PULITI Panoramica: che cosa è JDBC La API JDBC, introdotta per la prima volta con il JDK 1.0, è una API che permette di accedere a database relazionali

Dettagli

Siti web centrati sui dati Architettura MVC-2: i JavaBeans

Siti web centrati sui dati Architettura MVC-2: i JavaBeans Siti web centrati sui dati Architettura MVC-2: i JavaBeans 1 ALBERTO BELUSSI ANNO ACCADEMICO 2009/2010 Limiti dell approccio SEVLET UNICA La servlet svolge tre tipi di funzioni distinte: Interazione con

Dettagli

Programmazione Java Avanzata

Programmazione Java Avanzata Programmazione Java Avanzata Accesso ai Dati Ing. Giuseppe D'Aquì Testi Consigliati Eclipse In Action Core J2EE Patterns - DAO [http://java.sun.com/blueprints/corej2eepatterns/patterns/dataaccessobject.html]

Dettagli

Università degli Studi di Bologna Facoltà di Ingegneria. Tecnologie Web L-A A.A. 2014 2015. Esercitazione 08 DAO e Hibernate

Università degli Studi di Bologna Facoltà di Ingegneria. Tecnologie Web L-A A.A. 2014 2015. Esercitazione 08 DAO e Hibernate Università degli Studi di Bologna Facoltà di Ingegneria Tecnologie Web L-A A.A. 2014 2015 Esercitazione 08 DAO e Hibernate Agenda Pattern DAO e framework Hibernate progetto d'esempio relativo alla gestione

Dettagli

Architettura MVC-2: i JavaBeans

Architettura MVC-2: i JavaBeans Siti web centrati sui dati Architettura MVC-2: i JavaBeans Alberto Belussi anno accademico 2008/2009 Limiti dell approccio SEVLET UNICA La servlet svolge tre tipi di funzioni distinte: Interazione con

Dettagli

Basi di Dati: Corso di laboratorio

Basi di Dati: Corso di laboratorio Basi di Dati: Corso di laboratorio Lezione 10 Raffaella Gentilini 1 / 46 Sommario 1 Introduzione: DB e Programmazione 2 3 2 / 46 Approcci alla Programmazione di un DB Meccanismi Disponibili 1 Linguaggi

Dettagli

Laboratorio di Sistemi Fondamenti di JDBC (parte1) Java. Fondamenti di JDBC

Laboratorio di Sistemi Fondamenti di JDBC (parte1) Java. Fondamenti di JDBC Fondamenti di JDBC Concetto di driver Il dialogo fra applicazione e DBMS non è mai gestito direttamente ma passa in genere per un opportuno modulo software chiamato driver che agisce da interfaccia fra

Dettagli

19.1 - Lavorare con JDBC L'impiego di JDBC è semplice, e solitamente si articola attraverso quattro passi:

19.1 - Lavorare con JDBC L'impiego di JDBC è semplice, e solitamente si articola attraverso quattro passi: Lezione 19 Accesso ai database con JDBC JDBC (non è una sigla, secondo quanto sostenuto da Sun, anche se molti la interpretano come Java DataBase Connectivity) è un'interfaccia di programmazione che lavora

Dettagli

Caricamento della classe driver. Apertura della connessione. DriverManager.getConnection() Creazione di uno statement

Caricamento della classe driver. Apertura della connessione. DriverManager.getConnection() Creazione di uno statement JDBC Programmazione in Ambienti Distribuiti V 1.4 Marco Torchiano 2006 Uso di JDBC Caricamento della classe driver Class.forName() Apertura della connessione DriverManager.getConnection() Creazione di

Dettagli

JDBC: SQL NEI LINGUAGGI DI PROGRAMMAZIONE

JDBC: SQL NEI LINGUAGGI DI PROGRAMMAZIONE JDBC: SQL NEI LINGUAGGI DI PROGRAMMAZIONE Disheng Qiu disheng.qiu@gmail.com SQL e Applicazioni In applicazioni complesse, l utente non vuole eseguire comandi SQL, ma programmi, con poche scelte SQL non

Dettagli

Sviluppo di applicazioni per basi di dati

Sviluppo di applicazioni per basi di dati Sviluppo di applicazioni per basi di dati 1 Sviluppo di applicazioni per basi di dati Quattro parti: Gestione dati Business rules (vincoli di integrità e dati derivati) Logica applicativa Interfaccia utente

Dettagli

Gestione delle eccezioni in Java

Gestione delle eccezioni in Java Gestione delle eccezioni in Java - Introduzione al concetto di eccezioni E possibile definire un eccezione come un situazione imprevista che il flusso di un applicazione può incontrare. È possibile gestire

Dettagli

TUTORIAL. CREAZIONE DI TRIGGER IN ORACLE LITE 8i MEDIANTE CLASSI JAVA

TUTORIAL. CREAZIONE DI TRIGGER IN ORACLE LITE 8i MEDIANTE CLASSI JAVA TUTORIAL CREAZIONE DI TRIGGER IN ORACLE LITE 8i MEDIANTE CLASSI JAVA Michele de Nittis Generalità... 2 Modello di Caricamento e Pubblicazione... 3 Modello Per Allegato (Attachment)... 9 Esempio di creazione

Dettagli

Programmazione Java: JDBC

Programmazione Java: JDBC Programmazione Java: JDBC romina.eramo@univaq.it http://www.di.univaq.it/romina.eramo/tlp Roadmap Introduzione Risorse Driver Contesto Applicativo SQL Classi e interfacce Passi» Registrare un driver» Stabilire

Dettagli

Corso Online. We Train Italy info@wetrainitaly.it

Corso Online. We Train Italy info@wetrainitaly.it Corso Online Programmatore Java New Edition We Train Italy info@wetrainitaly.it Programma Generale del Corso Programmatore Java New Edition 1. Introduzione al corso Java da 0 al web Presentazione del corso

Dettagli

Quando si sa chiaramente come si deve comportare l applicazione si può analizzare una possibile soluzione applicativa.

Quando si sa chiaramente come si deve comportare l applicazione si può analizzare una possibile soluzione applicativa. Introduzione alla tecnologia JMX 1 Viene analizzata l architettura sottostante le Java Managment Extensions (JMX) mostrandone un utilizzo applicativo e analizzando altri possibili scenari d uso di Ivan

Dettagli

Dominio applicativo. Progettazione. v SQL incluso in codice applicativo v Embedded SQL v Cursori v Dynamic SQL v JDBC v Stored procedures

Dominio applicativo. Progettazione. v SQL incluso in codice applicativo v Embedded SQL v Cursori v Dynamic SQL v JDBC v Stored procedures Dominio applicativo (Capitolo 6) v SQL incluso in codice applicativo v Embedded SQL v Cursori v Dynamic SQL v JDBC v Stored procedures Basi di dati 1 Docente Claudia Amari 1 Progettazione PROGETTAZIONE

Dettagli

Accesso Web a Data Base

Accesso Web a Data Base Università degli Studi di Modena e Reggio Emilia Facoltà di Ingegneria Reggio Emilia CORSO DI TECNOLOGIE E APPLICAZIONI WEB Accesso Web a Data Base Ing. Marco Mamei Anno Accademico 2004-2005 M. Mamei -

Dettagli

Basi di dati. Il Linguaggio SQL. K. Donno - Il Linguaggio SQL

Basi di dati. Il Linguaggio SQL. K. Donno - Il Linguaggio SQL Basi di dati Il Linguaggio SQL Data Definition Language (DDL) Data Definition Language: insieme di istruzioni utilizzate per modificare la struttura della base di dati Ne fanno parte le istruzioni di inserimento,

Dettagli

Programmazione a Oggetti Modulo B

Programmazione a Oggetti Modulo B Programmazione a Oggetti Modulo B Lezione 5 Dott. Alessandro Roncato 08/11/2011 Riassunto Pattern Singleton Pattern Plolimorfismo Classi e Interfacce 2 Ereditarietà multipla In Java una classe può estendere

Dettagli

JAVA JDBC. Andrea BEI (andrea.bei@libero.it)

JAVA JDBC. Andrea BEI (andrea.bei@libero.it) JAVA JDBC Andrea BEI (andrea.bei@libero.it) JDBC: API JDBC (Java DataBase Connectivity) è una API per l accesso a DataBase relazionali sviluppata da SUN. Permette ad applicazioni JAVA di eseguire istruzioni

Dettagli

JDBC Un API JAVA per accedere a Basi di Dati Relazionali. Contenuti. Cos è JDBC? Introduzione a JDBC. Perché JDBC. Inside JDBC.

JDBC Un API JAVA per accedere a Basi di Dati Relazionali. Contenuti. Cos è JDBC? Introduzione a JDBC. Perché JDBC. Inside JDBC. JDBC Un API JAVA per accedere a Basi di Dati Relazionali 1 Contenuti Introduzione a JDBC Perché JDBC R, Architetture client-server, ODBC Inside JDBC Driver, classi, interfacce Un esempio 2 Cos è JDBC?

Dettagli

Java e PL/SQL. Simona Rotolo

Java e PL/SQL. Simona Rotolo Java e PL/SQL Simona Rotolo 2 Con l'uscita di Oracle 8i è possibile costruire componenti software che accedono ai dati Oracle utilizzando in modo congiunto i linguaggi PL/Sql e Java. In tal modo è possibile

Dettagli

SQL nei linguaggi di programmazione

SQL nei linguaggi di programmazione SQL nei linguaggi di programmazione Atzeni, Ceri, Paraboschi, Torlone Basi Di Dati Modelli e Linguaggi di Interrogazione, McGraw-Hill Italia, Capitolo 6 SQL in Linguaggi di Programmazione L uso diretto

Dettagli

Basi di Dati Esercitazione JDBC. Giugno 2007

Basi di Dati Esercitazione JDBC. Giugno 2007 Basi di Dati Esercitazione JDBC Giugno 2007 Esercizi Considerando il seguente schema: Fornitori (CodiceFornitore, Nome, Indirizzo, Citta) Prodotti (CodiceProdotto, Tipo, Marca, Modello) Catalogo (CodiceFornitore,

Dettagli

APPENDICE. Procedure in SQL (1)

APPENDICE. Procedure in SQL (1) APPENDICE Procedure in SQL Transazioni in SQL Embedded SQL Remote Procedure Call Appendice 1 Procedure in SQL (1) Standard SQL2 permette di definire procedure, associate a singoli comandi SQL, memorizzate

Dettagli

Activation In sintesi: è inutile avere attivi degli oggetti se non vengono utilizzati

Activation In sintesi: è inutile avere attivi degli oggetti se non vengono utilizzati Activation In generale i Sistemi ad oggetti distribuiti sono progettati per lavorare con oggetti persistenti. Dato che questi sistemi saranno composti da migliaia (forse milioni) di tali oggetti, sarebbe

Dettagli

Le transazioni. Dott. Doria Mauro doriamauro@gmail.com

Le transazioni. Dott. Doria Mauro doriamauro@gmail.com Hibernate Le transazioni Dott. Doria Mauro doriamauro@gmail.com Introduzione La demarcazione delle transazioni può essere fatta: In maniera programmatica: demarcazione all interno del codice applicativo.

Dettagli

Laboratorio di Basi di Dati e Multimedia

Laboratorio di Basi di Dati e Multimedia Laboratorio di Basi di Dati e Multimedia Laurea in Tecnologie dell Informazione: Multimedia Docente: Alessandra Di Pierro Email: dipierro@sci.univr.it Lezione 7 Java DataBase Connectivity JDBC consente

Dettagli

Esercitazione 4 JDBC

Esercitazione 4 JDBC JDBC Obiettivi dell esercitazione Familiarizzare con l'organizzazione dell'ambiente di lavoro per la realizzazione di applicazioni Java Utilizzare i costrutti di base della libreria JDBC per 1. la gestione

Dettagli

DBMS ED APPLICAZIONI (CAPITOLO 6) SQL incluso in codice applicativo Embedded SQL Cursori Dynamic SQL JDBC Stored procedures

DBMS ED APPLICAZIONI (CAPITOLO 6) SQL incluso in codice applicativo Embedded SQL Cursori Dynamic SQL JDBC Stored procedures 1 DBMS ED APPLICAZIONI (CAPITOLO 6) SQL incluso in codice applicativo Embedded SQL Cursori Dynamic SQL JDBC Stored procedures Progettazione 2 Dominio Applicativo PROGETTAZIONE CONCETTUALE PROGETTAZIONE

Dettagli

A. Bardine - Introduzione a PostgreSQL. PostgreSQL è un software relazionale e ad oggetti per la gestione di basi di dati

A. Bardine - Introduzione a PostgreSQL. PostgreSQL è un software relazionale e ad oggetti per la gestione di basi di dati Basi di dati PostgreSQL è un software relazionale e ad oggetti per la gestione di basi di dati PostgreSQL è Open-Source ed il suo sviluppo procede da 15 anni il suo codice sorgente è quindi disponibile

Dettagli

Corso di Web Programming

Corso di Web Programming Corso di Web Programming 11. PHP - Complementi Paolo Milazzo Dipartimento di Informatica, Università di Pisa http://www.di.unipi.it/ milazzo milazzo di.unipi.it Corso di Laurea in Informatica Applicata

Dettagli

SQL e linguaggi di programmazione Applicazioni ed SQL: architettura

SQL e linguaggi di programmazione Applicazioni ed SQL: architettura SQL e applicazioni Atzeni, Ceri, Paraboschi, Torlone Basi di dati McGraw-Hill, 1996-2002 Capitolo 5: SQL nei linguaggi di programmazione 21/10/2002 In applicazioni complesse, l utente non vuole eseguire

Dettagli

Laboratorio di reti II: Java Server Pages

Laboratorio di reti II: Java Server Pages Laboratorio di reti II: Java Server Pages Stefano Brocchi brocchi@dsi.unifi.it 6 aprile, 2009 Stefano Brocchi Laboratorio di reti II: Java Server Pages 6 aprile, 2009 1 / 34 JSP - Java Server Pages Le

Dettagli

Tool. Basi di Dati e Sistemi Informativi Prof. Marco Di Felice Dott.sa Sara Zuppiroli A.A. 2012-2013

Tool. Basi di Dati e Sistemi Informativi Prof. Marco Di Felice Dott.sa Sara Zuppiroli A.A. 2012-2013 Tool Basi di Dati e Sistemi Informativi Prof. Marco Di Felice Dott.sa Sara Zuppiroli A.A. 2012-2013 Basi di Dati e Sistemi Informativi () PostgreSQL A.A. 2012-2013 1 / 26 Gli strumenti che vedremo Basi

Dettagli

The world s most advanced class on PostgreSQL o quasi! 4 Marzo 8 Aprile 2015. L'Antipasto 11 Marzo

The world s most advanced class on PostgreSQL o quasi! 4 Marzo 8 Aprile 2015. L'Antipasto 11 Marzo The world s most advanced class on PostgreSQL o quasi! 4 Marzo 8 Aprile 2015 L'Antipasto 11 Marzo Riepilogo della puntata precedente ##################### Avviamo la macchina virtuale #####################

Dettagli

Capitoli 8 e 9. SQL embedded. Applicazioni tradizionali Applicazioni Internet. Sistemi di basi di dati Raghu Ramakrishnan, Johannes Gehrke

Capitoli 8 e 9. SQL embedded. Applicazioni tradizionali Applicazioni Internet. Sistemi di basi di dati Raghu Ramakrishnan, Johannes Gehrke Capitoli 8 e 9 Applicazioni tradizionali Applicazioni Internet SQL embedded SQL nel codice applicativo I comandi SQL possono essere chiamati dall interno di un programma in un linguaggio ospite (ad esempio

Dettagli

Il DBMS Oracle. Express Edition. Donatella Gubiani e Angelo Montanari

Il DBMS Oracle. Express Edition. Donatella Gubiani e Angelo Montanari Gubiani & Montanari Il DBMS Oracle 1 Il DBMS Oracle Express Edition Donatella Gubiani e Angelo Montanari Il DBMS Oracle Il DBMS Oracle Oracle 10g Express Edition Il DBMS Oracle (nelle sue versioni più

Dettagli

Basi di dati. Introduzione a PostgreSQL. K.Donno - Introduzione a PostgreSQL

Basi di dati. Introduzione a PostgreSQL. K.Donno - Introduzione a PostgreSQL Basi di dati Introduzione a PostgreSQL Introduzione a PostgreSQL PostgreSQL è un software relazionale e ad oggetti per la gestione di basi di dati PostgreSQL è Open-Source ed il suo sviluppo procede da

Dettagli

Basi di dati (8) Docente: Andrea Bulgarelli. Università di Modena e Reggio Emilia. andrea.bulgarelli@gmail.com Argomento: trigger e cursori (1.

Basi di dati (8) Docente: Andrea Bulgarelli. Università di Modena e Reggio Emilia. andrea.bulgarelli@gmail.com Argomento: trigger e cursori (1. Università di Modena e Reggio Emilia Basi di dati (8) Docente: andrea.bulgarelli@gmail.com Argomento: trigger e cursori (1.1) 1 Panoramica Trigger Creazione Tipi di trigger Tabelle inserted/deleted Esempi

Dettagli

Esercitazione 8. Basi di dati e web

Esercitazione 8. Basi di dati e web Esercitazione 8 Basi di dati e web Rev. 1 Basi di dati - prof. Silvio Salza - a.a. 2014-2015 E8-1 Basi di dati e web Una modalità tipica di accesso alle basi di dati è tramite interfacce web Esiste una

Dettagli

Gli EJB offrono vari vantaggi allo sviluppatore di una applicazione

Gli EJB offrono vari vantaggi allo sviluppatore di una applicazione Gli EJB offrono vari vantaggi allo sviluppatore di una applicazione Un ambiente di esecuzione che gestisce o naming di oggetti, sicurezza, concorrenza, transazioni, persistenza, distribuzione oggetti (location

Dettagli

Tecnologie di Sviluppo per il Web

Tecnologie di Sviluppo per il Web Tecnologie di Sviluppo per il Web Programmazione su Basi di Dati: ADO.NET versione 1.1 Questo lavoro è concesso in uso secondo i termini di una licenza Creative Commons (vedi ultima pagina) G. Mecca mecca@unibas.it

Dettagli

UNIVERSITA DI FIRENZE Facoltà di Ingegneria. Persistenza Applicazioni Enterprise Uso dei modelli

UNIVERSITA DI FIRENZE Facoltà di Ingegneria. Persistenza Applicazioni Enterprise Uso dei modelli UNIVERSITA DI FIRENZE Facoltà di Ingegneria Persistenza Applicazioni Enterprise Uso dei modelli 1 IL problema della persistenza APPLICAZIONE (programmi) (oggetti) DATI PERSISTENTI (file, record) (basi

Dettagli

Interoperabilità. Open Database Connectivity (ODBC)

Interoperabilità. Open Database Connectivity (ODBC) Interoperabilità L utilizzo contemporaneo di sorgenti di dati (data source) eterogenee in singole applicazioni è il principale problema in progetti complessi e distribuiti. La soluzione passa attraverso

Dettagli

APPENDICE B Le Active Server Page

APPENDICE B Le Active Server Page APPENDICE B Le Active Server Page B.1 Introduzione ad ASP La programmazione web è nata con la Common Gateway Interface. L interfaccia CGI tuttavia presenta dei limiti: ad esempio anche per semplici elaborazioni

Dettagli

MDAC. Attualmente la versione disponibile di MDAC è la 2.8 ma faremo riferimento alla 2.6. ADO Active Data Objects ADO OLE DB ODBC

MDAC. Attualmente la versione disponibile di MDAC è la 2.8 ma faremo riferimento alla 2.6. ADO Active Data Objects ADO OLE DB ODBC MDAC MDAC è l acronimo di Microsoft Data Access Component e fa parte della tecnologia Microsoft denominata Universal Data Access (UDA). Mette a disposizione una serie di componenti per l accesso a svariate

Dettagli

Basi di Dati: Corso di laboratorio

Basi di Dati: Corso di laboratorio Basi di Dati: Corso di laboratorio Lezione 1 Raffaella Gentilini 1 / 67 Sommario 1 Introduzine al Linguaggio SQL Concetti Preliminari 2 3 2 / 67 Concetti Preliminari Il linguaggio SQL SQL Acronimo per

Dettagli

Basi di dati e Web (Moduli: Laboratorio e Siti Web centrati sui Dati) Prova scritta del 14 luglio 2008

Basi di dati e Web (Moduli: Laboratorio e Siti Web centrati sui Dati) Prova scritta del 14 luglio 2008 Basi di dati e Web (Moduli: Laboratorio e Siti Web centrati sui Dati) Prova scritta del 14 luglio 2008 Avvertenze: e severamente vietato consultare libri e appunti; chiunque verrà trovato in possesso di

Dettagli

Lezione 8. Metadati, Viste e Trigger

Lezione 8. Metadati, Viste e Trigger Lezione 8 Metadati, Viste e Trigger Pag.1 Metadati e catalogo di sistema I metadati sono dati a proposito dei dati (quali tabelle esistono?, quali campi contengono?, quante tuple contengono?, ci sono vincoli

Dettagli

Servizi web in LabVIEW

Servizi web in LabVIEW Servizi web in LabVIEW Soluzioni possibili, come si utilizzano. 1 Soluzioni possibili WEB SERVER Dalla versione 5.1 di LabVIEW è possibile implementare un Web server che consente di operare da remoto sul

Dettagli

Oggetto: MASTER DI ALTA FORMAZIONE PROFESSIONALE IN PROGRAMMATORE JAVA PARTECIPAZIONE GRATUITA

Oggetto: MASTER DI ALTA FORMAZIONE PROFESSIONALE IN PROGRAMMATORE JAVA PARTECIPAZIONE GRATUITA Oggetto: MASTER DI ALTA FORMAZIONE PROFESSIONALE IN PROGRAMMATORE JAVA PARTECIPAZIONE GRATUITA Salerno Formazione, società operante nel settore della didattica, della formazione professionale e certificata

Dettagli

Mobilità di Codice. Massimo Merro Programmazione di Rete 128 / 144

Mobilità di Codice. Massimo Merro Programmazione di Rete 128 / 144 Mobilità di Codice Abbiamo già visto come un dato host possa trasmettere un oggetto (serializzabile) ad un altro host. Quest ultimo potrà eseguire l oggetto pur non possedendo il bytecode della classe

Dettagli

Esercitazione sulle libpq - libreria C per PostgreSQL

Esercitazione sulle libpq - libreria C per PostgreSQL Esercitazione sulle libpq - libreria C per PostgreSQL Roberto Tronci roberto.tronci@diee.unica.it Basi di Dati A.A. 2007/2008 Tronci ( roberto.tronci@diee.unica.it ) Esercitazione libpq Basi di Dati 2007/2008

Dettagli

Linguaggio Java. Robusto. Orientato agli oggetti. Protegge e gestisce dagli errori. Non permette costrutti pericolosi

Linguaggio Java. Robusto. Orientato agli oggetti. Protegge e gestisce dagli errori. Non permette costrutti pericolosi Linguaggio Java Robusto Non permette costrutti pericolosi Eredità Multipla Gestione della Memoria Orientato agli oggetti Ogni cosa ha un tipo Ogni tipo è un oggetto (quasi) Protegge e gestisce dagli errori

Dettagli

Laboratorio Progettazione Web PHP e MySQL. Andrea Marchetti IIT-CNR 2013/2014

Laboratorio Progettazione Web PHP e MySQL. Andrea Marchetti IIT-CNR 2013/2014 Laboratorio Progettazione Web PHP e MySQL Andrea Marchetti IIT-CNR 2013/2014 Architettura di una applicazione Web Browser Web HTTP Server Web API Dati Presentation Application Storage PHP e DataBase Quando

Dettagli

APPLICAZIONI DELLE BASI DI DATI

APPLICAZIONI DELLE BASI DI DATI APPLICAZIONI DELLE BASI DI DATI APPLICAZIONI TRADIZIONALI APPLICAZIONI INTERNET SQL EMBEDDED SQL nel codice applicativo! I comandi SQL possono essere chiamati dall interno di un programma in un linguaggio

Dettagli

SQL -DDL. FONDISTA(Nome, Nazione, Età) GAREGGIA(NomeFondista, NomeGara, Piazzamento) GARA(Nome, Luogo, Nazione, Lunghezza)

SQL -DDL. FONDISTA(Nome, Nazione, Età) GAREGGIA(NomeFondista, NomeGara, Piazzamento) GARA(Nome, Luogo, Nazione, Lunghezza) 26/03/2013 SQL SQL -DDL Esercizio 4.3 Dare le definizioni SQL delle tre tabelle FONDISTA(Nome, Nazione, Età) GAREGGIA(NomeFondista, NomeGara, Piazzamento) GARA(Nome, Luogo, Nazione, Lunghezza) rappresentando

Dettagli

Comprendere ADO.NET. La guida definitiva per comprendere a fondo ADO

Comprendere ADO.NET. La guida definitiva per comprendere a fondo ADO 060-063 Database 3-03-2005 16:23 Pagina 62 DATABASE La guida definitiva per comprendere a fondo ADO Accesso ai DB con Visual Basic.Net 2003 L ultimo articolo che ci aiuterà ad interagire con i database,

Dettagli

Suggerimenti per lo Sviluppo delle Applicazioni con PL/SQL. Simona Rotolo

Suggerimenti per lo Sviluppo delle Applicazioni con PL/SQL. Simona Rotolo Suggerimenti per lo Sviluppo delle Applicazioni con PL/SQL Simona Rotolo 2 Questo documento, rivolto a chi sviluppa codice in PL/Sql, è stato redatto al fine di fornire degli standard di sviluppo che aiuteranno

Dettagli

DATABASE IN RETE E PROGRAMMAZIONE LATO SERVER

DATABASE IN RETE E PROGRAMMAZIONE LATO SERVER DATABASE IN RETE E PROGRAMMAZIONE LATO SERVER L architettura CLIENT SERVER è l architettura standard dei sistemi di rete, dove i computer detti SERVER forniscono servizi, e computer detti CLIENT, richiedono

Dettagli

MySQL Command Line Client: operazioni fondamentali

MySQL Command Line Client: operazioni fondamentali MySQL Command Line Client: operazioni fondamentali INTRODUZIONE Il RDBMS MySQL, oltre a fornire un applicazione che abbia un interfaccia user-friendly, ha a disposizione anche un altro client, che svolge

Dettagli

Agent and Object Technology Lab Dipartimento di Ingegneria dell Informazione Università degli Studi di Parma. Ingegneria del software A.

Agent and Object Technology Lab Dipartimento di Ingegneria dell Informazione Università degli Studi di Parma. Ingegneria del software A. Agent and Object Technology Lab Dipartimento di Ingegneria dell Informazione Università degli Studi di Parma Ingegneria del software A Apache Ant Michele Tomaiuolo Progetto Apache Open source, community

Dettagli

Tecnologie Web L-A. Java e HTTP. Dario Bottazzi Tel. 051 2093541, E-Mail: dario.bottazzi@unibo.it, SkypeID: dariobottazzi. Java e TCP/IP in a Nutshell

Tecnologie Web L-A. Java e HTTP. Dario Bottazzi Tel. 051 2093541, E-Mail: dario.bottazzi@unibo.it, SkypeID: dariobottazzi. Java e TCP/IP in a Nutshell Tecnologie Web L-A Java e HTTP Dario Bottazzi Tel. 051 2093541, E-Mail: dario.bottazzi@unibo.it, SkypeID: dariobottazzi Java e TCP/IP in a Nutshell! java.net.inetaddress: rappresenta un indirizzo IP e

Dettagli

RMI: metodi equals e hashcode

RMI: metodi equals e hashcode RMI: metodi equals e hashcode Per verificare se due oggetti remoti contengono gli stessi dati, la chiamata indirizzata al metodo equals() avrebbe bisogno di contattare i server dove si trovano gli oggetti

Dettagli

PostgreSQL - amministrazione

PostgreSQL - amministrazione PostgreSQL - amministrazione ITPUG - Pisa - 08/05/2009 Gabriele Bartolini Flavio Casadei Della Chiesa Luca Ferrari Marco Tofanari Associazione Italiana PostgreSQL Users Group www.itpug.org Pisa, 8 Maggio

Dettagli

Corso di Informatica Modulo T3 B2 - Database in rete

Corso di Informatica Modulo T3 B2 - Database in rete Corso di Informatica Modulo T3 B2 - Database in rete 1 Prerequisiti Programmazione web Applicazione web Modello OSI Architettura client/server Conoscenze generali sui database Tecnologia ADO in Visual

Dettagli

Programmazione delle basi di dati attraverso JDBC

Programmazione delle basi di dati attraverso JDBC Programmazione delle basi di dati attraverso JDBC Dispense di Basi di dati Queste breve note non hanno la pretesa di essere un nuovo libro di testo sulle tecnologie informatiche. Vogliono invece costituire

Dettagli

MySQL Database Management System

MySQL Database Management System MySQL Database Management System http://www.mysql.com/ DATABASE RELAZIONALI Un database è una collezione strutturata di informazioni. I database sono delle strutture nelle quali è possibile memorizzare

Dettagli

PHP e Structured Query Language

PHP e Structured Query Language Esercitazioni del corso di Tecnologie per la Comunicazione Aziendale PHP e Structured Query Language Marco Loregian loregian@disco.unimib.it www.siti.disco.unimib.it/didattica/tca2008 Interrogazioni (ripasso)

Dettagli

Uso dei data bases con PHP. Prof. Francesco Accaino Iis Altiero Spinelli Sesto Sa Giovanni

Uso dei data bases con PHP. Prof. Francesco Accaino Iis Altiero Spinelli Sesto Sa Giovanni Uso dei data bases con PHP Prof. Francesco Accaino Iis Altiero Spinelli Sesto Sa Giovanni MDAC MDAC è l acronimo di Microsoft Data Access Component e fa parte della tecnologia Microsoft denominata Universal

Dettagli

Programmazione Java Avanzata Concetti su Java

Programmazione Java Avanzata Concetti su Java Programmazione Java Avanzata Concetti su Java Ing. Giuseppe D'Aquì Testi di Riferimento Java ( R. Liguori, P. Liguori), O'Reilly Hops Tecniche Nuove (2008) Java Virtual Machine Il codice scritto in Java

Dettagli