Java EE 1 Ingegneria del Software (parte II) Andrea Bei CBD (Component Based Development) interfaccia La definizione secondo il glossario "UML-User Guide" : "Un componente è una parte fisica e sostituibile di un sistema che implementa un insieme di interfacce." L’implementazione (numero e classi utilizzate) è nascosta Lo sviluppo a componenti incrementa la qualità del SW componente Ovvero: Manutenibilità, Leggibilità, Riusabilità, Portabilità, Affidabilità Applicazioni progettate secondo il paradigma a componenti sono chiamate component-based 2 Application Server (AS) Le applicazioni component based possono essere installate in component container ( o più semplicemente container) Un AS è costituito da un insieme di container per componenti di diverso tipo (EJB Container, WEB Container, WEB Server) Lo scopo principale di un container è gestire il ciclo di vita dei componenti (creazione, distruzione, pooling, passivazione, …) Tra gli altri principali servizi offerti dagli application server Gestione Gestione Gestione Gestione dello stato della sicurezza dell’accesso ai dati delle transazioni Per essere installato (il termine corretto è deploy) su un AS un componente deve aderire ad opportune specifiche 3 Applicazioni di classe Enterprise Sono sistemi informatici utilizzati in medie o grandi organizzazioni a supporto di sistemi informativi critici. Ad esempio: ERP (Enterprise Resource Planning): Contabilità, Personale, Inventario, .Controllo di gestione CRM (Customer Relationship Management): sistemi per la gestione dei clienti, dei contatti ed il tracciamento degli eventi associati ai clienti SRM (Service Request Management): gestione e processamento di richieste Una applicazione di classe Enterprise deve avere le seguenti caratteristiche: Performante: deve servire più richieste concorrenti (multiuser) in maniera efficiente. Tale caratteristica si ottiene attraverso i servizi di caching e pooling. Distribuita: i componenti devono poter essere distribuiti su server diversi Scalabile: l’applicazione garantire il mantenimento dei tempi di risposta all’aumentare degli utenti concorrenti. (ad es: deve essere possibile scalare orizzontalmente mediante il clustering) Sicura: gli utenti devono essere autenticati e autorizzati Affidabile Portabile Transazionale 4 Java EE Java Enterprise Edition è un insieme di tecnologie e API Supporta un approccio component-based per la progettazione, lo sviluppo, l’assemblaggio e la messa in esercizio di applicazioni di classe enterprise Definisce le specifiche per i vendor di application server Java EEcompliant Comprende le seguenti principali tecnologie/API JSP Java Server Pages JSF Java Server Faces Java Servlets Servlet API Web Services EJB Enterprise JavaBeans JNDI Java Naming and Directory Interface JDBC 2.0 Extensions Java Database Connectivity Extensions RMI-IIOP RMI over Internet Inter-Orb Protocol JMS Java Message Service Java Mail Java Mail JAF JavaBeans Activation Framework JTA Java Transaction API XML Extensible Markup Language JMX Java Management Extensions 5 Application Server Tra gli application server Java EECompliant più conosciuti: IBM WebSphere Bea WebLogic Server Oracle AS (OC4J) JBoss (Open Source) Glassfish (Open Source) Tomcat (Open Source) Tutti gli AS elencati sopra sono dotati di Web Container + EJB Container tranne Tomcat 6 Componenti e strati Java EE La piattaforma Java EE supporta il pattern architetturale Layer Il numero di Layer (o Tier) adottati è una scelta di progettazione Un modello classico di applicazione Java EE prevede almeno 4 Layer I – Presentazione o Client Tier: Componenti client: Applicazioni e Thin Client (CL) HTML (CL) II – Applicazione o Web Tier Componenti Web: Servlet,JSP,JSF, JavaBean, POJO (AS) III - Logica di business o Business Tier Componenti di business: EJB (Enterprise Java Bean) e POJO (AS) IV – Persistenza o EIS Tier Componenti EIS (Enterprise Information Systems) I sistemi per la persistenza dei dati (DB, ORM, …) (Object Relational Mapping) 7 Componenti e strati J2EE Un modello completo prevede la suddivisione del layer logica di business nei due layer Servizi e Dominio. Si ottengono 5 Layer Tale modello è molto diffuso ed è quello di riferimento per il corso Livello Responsabilità Tecnologia Presentazione User Interface Componenti Client HTML/Javascript/Swing Applicazione sintassi,interazione con lo strato dei servizi, workflow degli use case (Controller di sessione) Componenti Web Servlet, JSP, JSF, JavaBean Servizi transazioni, logica di business e di workflow Componenti di Business EJB (Session bean) e POJO Dominio semantica, modello di dominio, logica business di dominio Componenti di Business (EJB) Entity bean e POJO Persistenza Accesso e gestione dati Componenti EIS RDBMS/ODBMS/ORM 8 Componenti e strati J2EE E’ possibile usare l’architettura di riferimento in maniera flessibile. Es: Unire differenti strati logici usando una sola tecnologia. Applicazione Web con strati di servizio e dominio realizzati con semplici JavaBean. Non vengono utilizzati EJB nel Business Tier Usare solo un sottoinsieme degli strati Applicazione Client-Server senza l’utilizzo del Web Tier. Lo strato di presentazione è realizzato con classi Swing, gli strati di applicazione, servizio, dominio sono realizzati con EJB o semplici JavaBean 9 Sfruttando le tecnologie offerte dalle piattaforme Java SE+ Java EE è possibile sviluppare applicazione con caratteristiche "Enteprise" Le tecnologie fondamentali sono: JDBC, Servlet, JSP, EJB, JNDI Presentazione J2EE Application Server Applicazione Persistenza JDBC Componenti e strati J2EE Servizi Dominio JNDI 10 Il percorso didattico Presentazione Persistenza Architettura "semplice" 1. 2. Presentazione Presentazione JDBC Servlet Persistenza J2EE Application Server Architettura "media" complessità + 1. JSP 2. MVC Persistenza Architettura completa: + 1. EJB 2. JNDI Gli strati di applicazione, servizi e dominio sono implementati dalle tecnologie presenti nel tier 2 11 A destra gli argomenti che sono via via spiegati a partire dalla architettura "semplice" Architettura "semplice", Lo strato di presentazione Presentazione (Client Tier) Browser (Thin Client) Interpreta le pagine HTML generate dinamicamente dai componenti web Applet (Thin/Thick Client) Piccole applicazioni Java realizzate mediante le API Swing Sono eseguite all’"interno" del browser (su una JVM associata al browser) Sono classi che estendono java.applet.Applet o javax.swing.JApplet 12 Lo strato di persistenza Persistenza (EIS Tier) E’ lo strato responsabile della persistenza dei dati. E’ implementato da sistemi EIS (Enterprise Information System). Questi possono essere: DBMS (relazionali (RDBMS), a oggetti (ODBMS), …) Sistemi ORM (Object Relational Mapping) (es: Hibernate) creano una rappresentazione a oggetti di dati memorizzati in database relazionali Sistemi Informativi preesistenti (Sistemi Legacy) Nel caso comune in cui il sistema EIS coincide con un RDBMS la comunicazione t l t t di b i ( i i + 13 JDBC JDBC (Java DataBase Connectivity) è una API per l’accesso a DataBase relazionali Permette ad applicazioni JAVA di eseguire istruzioni SQL su database relazionali e gestire i risultati restituiti. JDBC definisce delle classi per rappresentare: connessioni a database istruzioni SQL result sets (insieme dei record restituiti da una Query SQL) database metadata (dati che descrivono la struttura del DB), ecc. è organizzata in diversi "strati": l’applicazione vede solo lo strato superiore, che è indipendente dal database che viene interrogato il compito di interfacciarsi effettivamente con il database è delegato ad una serie di driver sottostanti, che possono essere scritti in codice Java o nativo. 14 JDBC Presentazione Applicazione Servizi Dominio Persistenza 15 ODBC ODBC (Open DataBase Connectivity) è una API Microsoft per l’accesso a RDBMS Nei sistemi operativi Microsoft è presente il Data Source Administrator che permette di dichiarare al sistema operativo le fonti dati ODBC usate Una fonte dati ODBC è caratterizzata da: un un nome: il DSN (Data Source Name) driver ODBC per la comunicazione con il DBMS (Oracle, SQL Server, Access) il riferimento ad un database (il nome del DB) Le applicazioni instaurano una connessione con il database riferendosi al nome della fonte dati relativa. 16 JDBC JDBC-ODBC Bridge Driver: implementa un "ponte" di comunicazione tra JDBC e ODBC; Permette ad applicazioni JAVA (tramite JDBC) di accedere a database registrati via ODBC API Native: convertono chiamate JDBC in chiamate alle API proprietarie dei vari DBMS (Oracle, Sybase, Informix, DB2, Postgres, MySQL) Driver 100% JAVA Basati su un protocollo indipendente dal DBMS (JDBC-Net): traducono le chiamate JDBC in un protocollo indipendente dal DBMS. Tale protocollo viene poi ritradotto da un server nel protocollo specifico del DBMS. Il server permette di connettere una applicazione sviluppata interamente in JAVA ai vari DBMS. Basati sul protocollo del DBMS: traducono le chiamate JDBC nel protocollo usato dal DBMS. Questo permette una chiamata diretta dal client al server DBMS 17 JDBC 18 JDBC: Classi, interfacce e metodi principali Classe java.sql.DriverManager: fornisce le funzionalità base di un gestore di driver. I metodi sono: Connection getConnection(url,user,password): crea una connessione con un DB void setLoginTimeout(int): imposta il timeout di connessione int getLoginTimeout(): restituisce il timeout di connessione setLogStream( PrintStream ): imposta lo Stream di log PrintStream getLogStream(): accede allo Stream di Log void println(String): scrive un messaggio sul Log Interfaccia java.sql.Connection: rappresenta una connessione con uno specifico database. I metodi sono: void close(): chiude la connessione Statement createStatement(): crea e restituisce un oggetto di tipo Statement DatabaseMetaData getMetaData(): restituisce informazioni sulla struttura del database setAutoCommit(boolean): indica se presente o no l’autocommit (default=true) commit(): rende effettive le istruzioni SQL eseguite dall’ultimo commit rollback(): annulla le istruzioni SQL eseguite dall’ultimo commit 19 JDBC: Classi, interfacce e metodi principali Classe java.sql.Statement: un oggetto di tipo Statement è usato per eseguire delle istruzioni SQL. I metodi sono: ResultSet executeQuery( String ): esegue una Query SQL. Restituisce un oggetto di tipo ResultSet che rappresenta il risultato della Query int executeUpdate( String ): esegue una istruzione SQL che modifica la struttura o i dati del database( CREATE, INSERT, ecc..). int è il numero di righe modificate boolean execute( String ): esegue un comando SQL di interrogazione o modifica ResultSet getResultSet(): restituisce il risultato dell’ultima istruzione SQL eseguita con execute (null se l’istruzione era di modifica) int getUpdateCount(): restituisce il numero di righe coinvolte nell’ultima istruzione SQL eseguita con execute. void setQueryTimeout(int) e int getQueryTimeout(): accesso al timeout Classe java.sql.ResultSet: un oggetto di tipo ResultSet rappresenta il risultato di una Query. I metodi sono: getXXX("Nome Campo") con XXX=Float,String,Byte,Short;Long ….. Restituisce del record corrente il valore del campo passato come argomento next() : Aggiorna il puntatore al record corrente facendolo avanzare di un record in JDBC2.0 ci sono anche: absolute(int), relative(int) e previous() 20 Connessione con un DBMS JDBC-ODBC Driver / API Native Per effettuare una connessione con un DBMS è necessario: Effettuare l’import delle classi del package java.sql Caricare il driver di accesso a DB con l’istruzione Class.forName(<path completo della classe che implementa il driver>); individua carica ed esegue il link della classe passata come parametro Instaurare la connessione con il DBMS con l’istruzione: Connection con = DriverManager.getConnection(url, <login>, <password>); url è di tipo String ed ha la sintassi "jdbc:<subprotocol>:<subname>" dove: <subprotocol>: è il sottoprotocollo (es: odbc) <subname>: serve ad identificare la sorgente dei dati. 21 Connessione con un DBMS esempi Es: connessione con il DBMS Access libreria.mdb associato ad una fonte dati ODBC chiamata "libreria" con login="libreria" e password="libreria" Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); String url="jdbc:odbc:libreria"; Connection con =DriverManager.getConnection(url, "libreria", "libreria"); Es: connessione con il DBMS open source Postgres "mynewdb" sulla macchina 192.168.0.3 (www.postgresql.org) Class.forName( "org.postgresql.Driver" ); String url = "jdbc:postgresql://192.168.0.3/mynewdb"; Connection con = DriverManager.getConnection( url, USER , PASS ); 22 Connessione con un DBMS esempi Es: connessione con db Oracle 1. Copiare i file contenenti i driver (scaricabili dal sito Oracle) classes12.zip, jndi.zip in $ORACLE_HOME/jdbc/lib/ 2. aggiornare il CLASSPATH inserendo "$ORACLE_HOME/jdbc/lib/classes12.zip:$ORACLE_HOME/jdbc/lib/jndi.zip" 3. Eseguire la connessione al DataBase Class.forName("oracle.jdbc.driver.OracleDriver"); String url="jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=150.146.1.98) (PORT=1521))(CONNECT_DATA=(SID=ID_DB)))"; Connection con =DriverManager.getConnection(url, "login", "password"); 23 Istruzioni SQL Stabilita una connessione è possibile eseguire istruzioni SQL creare un oggetto di tipo Statement. Se la connessione è descritta dall’oggetto con l’istruzione è: Statement stmt = con.createStatement(); invocare i metodi dell’oggetto Statement: int executeUpdate("<istruzione SQL>"): per istruzioni di tipo CREATE, DROP, DELETE, INSERT, UPDATE stmt.executeUpdate("create table Anagrafica"+ "( Nome varchar(32)," + " Cognome varchar(32))"); ResultSet executeQuery("<istruzione SQL>") è usato per query stmt.executeQuery("select * from Libro"+ " where Titolo like \"Moby Dick%\" "); 24 Accesso al risultato delle query Il metodo executeQuery restituisce un oggetto di tipo ResultSet Un ResultSet è l’insieme di record che costituiscono il risultato di una query. Su quest’insieme viene mantenuto un puntatore alla posizione corrente. I l puntatore viene posto sul primo record alla prima invocazione del metodo next. String query = "SELECT Titolo, ISBN FROM Libro"; ResultSet rs = stmt.executeQuery(query); while (rs.next()) { String s = rs.getString("Titolo"); String c = rs.getString("ISBN"); System.out.println(s + " " + c); } 25 Esempio import java.sql.*; class provaJDBC { public static void main(String arg[]) throws Exception { Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); String url="jdbc:odbc:libreria"; Connection con=DriverManager.getConnection(url,"libreria","libreria"); Statement stmt = con.createStatement(); stmt.executeUpdate("create table Anagrafica"+ "( Nome varchar(32)," + " Cognome varchar(32))"); stmt.executeUpdate("insert into Anagrafica values (‘Giacomo’,’Leopardi’)"); ResultSet rs=stmt.executeQuery("select Nome,Cognome from Anagrafica"); while (rs.next()) { System.out.println(rs.getString("Nome")+" "+rs.getString("Cognome")); } }} 26 Prepared statement è una istruzione SQL precompilata dal DBMS l’esecuzione di una query è più efficiente (si risparmia il passo di compilazione del DBMS) conviene quando occorre eseguire molte volte la stessa query e’ possibile il passaggio di parametri PreparedStatement updateSales = con.prepareStatement( "UPDATE COFFEES SET SALES = ? WHERE COF_NAME LIKE ? "); updateSales.setInt(1, 75); updateSales.setString(2, "Colombian"); int n=updateSales.executeUpdate(); (1) creazione: i parametri sono specificati con "?" (2) passaggio parametri: posizionale (3) esecuzione n=numero di righe modificate 27 Prepared statement PreparedStatement updateSales; String updateString = "update COFFEES " + "set SALES = ? where COF_NAME like ?"; updateSales = con.prepareStatement(updateString); int [] salesForWeek = {175, 150, 60, 155, 90}; String [] coffees = {"Colombian", "French_Roast", "Espresso", "Colombian_Decaf", "French_Roast_Decaf"}; int len = coffees.length; for(int i = 0; i < len; i++) { updateSales.setInt(1, salesForWeek[i]); updateSales.setString(2, coffees[i]); updateSales.executeUpdate(); } 28 Transazioni una transazione è un insieme di operazioni su un database che soddisfa le seguenti proprietà (ACID) 1. Atomicity 2. Consistency: 3. l’esecuzione della transazione fa transitare il db da uno stato consistente ad un altro stato consistente (durante l’esecuzione è possibile la "non consistenza") Isolation 4. le operazioni vengono eseguite in modo atomico "tutte a buon fine o nessuna" le transazioni concorrenti sono isolate l’una dall’altra. L’una non deve vedere i dati che l’altra sta modificando. Durability i dati sopravvivono a crash. Esiste un log transazionale che registra tutte le operazioni eseguite sul db. E’ possibile risalire ad un punto di consistenza. 29 Transazioni I comandi classici dei DBMS per la gestione delle transazioni sono: COMMIT rende definitivo sul DB ciò che è stato fatto dalla transazione chiude la transazione ROLLBACK annulla sul DB ciò che è stato fatto dalla transazione. riporta il DB allo stato consistente in cui era prima che iniziasse la transazione per soddisfare la Atomicity e la Consistency viene eseguito se una delle operazioni della transazione non va a buon fine 30 Transazioni ed eccezioni disabilito ’AutoCommit try { con.setAutoCommit(false); PreparedStatement updateSales = con.prepareStatement( "UPDATE COFFEES SET SALES = ? se arrivo qui le operazioni WHERE COF_NAME LIKE ?"); SQL sono andate a buon updateSales.setInt(1, 50); fine. eseguo il COMMIT e updateSales.setString(2, "Colombian"); chiudo la transazione. updateSales.executeUpdate(); PreparedStatement updateTotal = con.prepareStatement( "UPDATE COFFEES SET TOTAL = TOTAL + ? WHERE COF_NAME LIKE ?"); updateTotal.setInt(1, 50); updateTotal.setString(2, "Colombian"); se qualche operazione updateTotal.executeUpdate(); SQL non va a buon fine con.commit(); viene catturata con.setAutoCommit(true); l’eccezione. } eseguo il ROLLBACK e catxh (SQLException e){ annullo la transazione if (con!=null) con.roolback()} 31 Es: sito WEB di una catena di librerie Ogni libreria possiede un accesso WEB Il fornitore del servizio fornisce un WEB Server che pubblica su WEB i dati relativi ai libri venduti (Autore, Titolo, Prezzo, Disponibilità nei vari punti vendita, ecc.) I dati sui libri e sulla loro disponibilità vengono inseriti da un operatore di ogni libreria in base ai libri acquistati e venduti Cliente libreria 1 libreria 2 Application DBMS Server Internet libreria N 32 Esempio: sito WEB di una catena di libreri Use Case Diagram 33 Esempio: sito WEB di una catena di librerie nome Prezzo Titolo Editore Anno copie Cod libreria LIBRERIA LIBRO (1,1) GENERE (1,1) (1,n) (1,n) (1,1) ISBN Cod_genere Genere Schema ER ( può essere fatto in UML !) (1,n) AUTORE Cod_autore Cognome Nome Anno di nascita Luogo di nascita 34 Esempio: sito WEB di una catena di libreri Architettura Applicativa (Package Diagram) Strato di dominio In questo caso è un semplice Facade verso il DB. Deve: E’ composto da Incapsulare le istruzioni (SQL) di comunicazione con il DB Offrire al livello superiore metodi indipendenti dal paradigma relazionale classi dette "DAO" (Data Access Object): incapsulano la logica di connessione e le istruzioni SQL (in questo caso una sola) classi dette Value Objects o DTO (Data Transfer Object) sevono per rappresentare "a oggetti" i dati relazionali Strati di servizio/applicazione Strato di persistenza (un db MS Access) Servizio/ Applicazione Dominio Persistenza 35 Esempio: sito WEB di una catena di librerie Class Diagram Dominio DAO Value Objects 36 Esempio: sito WEB di una catena di librerie I metodi principali della classe Libreria public Libreria(fonteDatiODBC, userODBC, passwordODBC): costrutt. public Collection ricercaPerGenere(String genere): restituisce una Collection di oggetti di tipo Libro con il genere passato come parametro. public Collection ricercaPerAutore(String nome): restituisce una Collection di oggetti di tipo Libro scritti dall’autore passato come param. public Collection ricercaPerTitolo(String titolo):restituisce una Collection contenente gli oggetti di tipo Libro che hanno il titolo passato come parametro. public void inserisciLibro(Libro l): insert nel database dei dati dell’oggetto Libro private int inserisciAutore(Autore a): insert nel database dei dati dell’oggetto Autore. Ritorna il codiceAutore, un numero che identifica univocamente l’autore. public void aggiornaCopie(String ISBN,String lib,int copie): Aggiorna le copie del libro ISBN della libreria lib. Copie può essere positivo o negativo public Libro getSchedaLibro(String ISBN): restituisce l’ oggetto di tipo Libro che ha come ISBN il codice passato come parametro 37 Implementazione:il DB Access libreria.mdb AUTORE Cod_autore Cognome 0 Melville 1 Hesse 3 Dick 4 Hofstader 5 Russel 6 Pirsig 7 Clarke Nome Herman Herman Philip Douglas Bertrand Robert Arthur COPIE Libreria 1 1 1 2 2 3 ISBN 88-347-0098-8 88-450-0701-1 88-460-0739-2 88-450-0701-1 88-459-0699-X 88-459-0734-1 Anno di nascita 1819 1847 1920 1945 1872 1928 1917 Luogo di nascita New York Estonia New York New York New York Minnesota Inghilterra LIBRERIA Copie 10 16 30 15 20 40 Cod_Libreria Nome 1 Feltrinelli 2 Apogeo 3 Ricordi 38 Implementazione:il DB Access libreria.mdb LIBRO ISBN 88-347-0098-8 88-450-0701-1 88-459-0468-7 88-459-0699-X 88-459-0734-1 88-459-0755-4 88-459-1095-4 88-460-0739-2 88-7819-669-X Titolo Ubik Storia della filosofia occidentale Amicizia Knulp Lo Zen e l'arte della manutenz… Goedel, Escher, Bach Moby Dick Lila 2001: Odissea nello spazio Editore Anno Cod_autor Cod genere Fanucci 1969 3 2 Mondadori 1977 5 0 Newton 1920 1 1 Newton 1915 1 1 Adelphi 1974 6 1 Adelphi 1992 4 0 Adelphi 1851 0 1 Adelphi 1985 6 1 Mondadori 1968 7 2 Prezzo L. 20.000 L. 15.000 L. 5.000 L. 5.000 L. 18.000 L. 20.000 L. 18.000 L. 15.000 L. 16.000 GENERE Cod_genere 0 1 2 3 Genere Saggio Romanzo Fantascienza Giallo 39 Value Objects: Libro class Libro { String ISBN; String titolo; String editore; int anno; Autore autore; String genere; int prezzo; // serve ha mantenere tutte le informazioni di //un Libro compreso i dettagli sull’autore Libro (String ISBN, String titolo, String editore, Int anno, Autore autore, String genere, Int prezzo) { this.ISBN=ISBN; this.titolo=titolo; .. this.autore=autore; } public String getISBN() { return ISBN;} public void setISBN(String ISBN) { this.ISBN=ISBN;} ... 40 Value Objects: Autore class Autore { // serve ha mantenere tutte le informazioni // su un autore String nome; String cognome; int dataDiNascita; String luogoDiNascita; Autore (String nome, String cognome, int dataDiNascita, String luogoDiNascita) { this.nome=nome; this.cognome=cognome; ... } public String getNome() { return nome;} public void setNome(String nome) { this.nome=nome;} ... 41 Libreria: implementazione del costruttore import java.sql.*; import java.io.*; class Libreria { Connection con=null; Statement stmt=null; String fonteDatiODBC=null; String userODBC=null; String passwordODBC=null; import java.util.*; Libreria(String fonteDatiODBC,String userODBC, String passwordODBC) // costruttore { this.fonteDatiODBC= fonteDatiODBC; this.userODBC= userODBC; this.passwordODBC= passwordODBC; } 42 Libreria:implementazione di metodi di utilità ... private ResultSet executeQuery(String Query) { // questo metodo serve solo per catturare le eccezioni del metodo // executeQuery ResultSet rs=null; try { rs=stmt.executeQuery(Query); } catch(SQLException e) { System.out.println("Problemi con l'esecuzione della Query SQL: "+ Query);} return(rs); } 43 Libreria:implementazione di metodi di utilità private void createConnection() { try { Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); // carico il driver JdbcOdbc } catch(ClassNotFoundException e) { System.out.println("Driver Jdbc-Odbc non presente"+e.getMessage()); } String url="jdbc:odbc:"+fonteDatiODBC; Try { con = DriverManager.getConnection(url, userODBC, passwordODBC); //eseguo la connessione stmt=con.createStatement(); // creo un oggetto di tipo Statement } catch(SQLException e) { System.out.println("Problemi nella apertura di sessione con la fonte dati "+ fonteDatiODBC+"\n"+"verificare l'esistenza della fontedati e la correttezza di User e Password");} } private void closeConnection() { Con.close(); Con=null; Stmt=null} 44 Libreria:implementazione di ricercaPerGenere public Collection ricercaPerGenere(String genere) { createConnection(); String Query="SELECT ISBN,Titolo,Editore,Anno,Genere,Prezzp, " Cognome,Nome,Anno_di_Nascita," " Luogo_di_Nascita "+ "FROM Genere, Libro , Autore"+ "WHERE Genere.Cod_genere=Libro.Cod_genere "+ "AND Genere.genere = '"+genere+"'"+ "AND Libro.cod_autore=Autore.cod_autore"; Collection a = new ArrayList(); ResultSet rs=null; rs=executeQuery(Query); try { while (rs.next()) { Autore autore= new Autore(rs.getString(7),rs.getString(8), rs.getString(9), rs.getString(10)); Libro libro= new Libro(rs.getString(1),rs.getString(2),rs.getString(3),rs.getString(4), rs.getString(5), rs.getString(6),autore); a.add(libro); } } catch(SQLException e) {System.out.println("Errore nella navigazione del ResultSet");} closeConnection(); return a;} 45 Libreria: implementazione di inserisciAutore private int inserisciAutore(Autore a) { // la classe Autore ha solo metodi setter e createConnection(); // getter per le variabili cognome, nome, int cod_autore=0; // annoDiNascita, luogoDiNascita String query="SELECT * "+ // verifico se l’autore è già presente "FROM Autore "+ "WHERE Nome='"+a.getNome()+"' and Cognome='"+a.getCognome()+"’"; try { ResultSet rs=executeQuery(Query); if (rs.next()) { cod_autore=rs.getInt("Cod_autore"); closeConnection(); return(cod_autore); // se è gia presente retituisco il codice relativo } query="SELECT MAX(Cod_autore) FROM Autore"; // altrimenti seleziono il massimo Cod_autore ResultSet rs=executeQuery(Query); rs.next(); cod_autore=rs.getInt(1)+1; // il nuovo Cod_autore è il max + 1 Query="INSERT INTO AUTORE (cod_autore,Cognome,Nome,Anno_di_nascita,Luogo_di_nascita) "+ " VALUES ("+cod_autore+",'"+a.getCognome()+"','"+a.getNome()+"',"+ a.getAnnoDiNascita()+",'"+a.getLuogoDiNascita()+"')"; int rc=executeUpdate(Query); } catch(SQLException e) {System.out.println("Errore nella navigazione del ResultSet");}} closeConnection();} 46 Libreria: implementazione di inserisciLibro public void inserisciLibro(Libro l) { // la classe Libro ha solo metodi createConnection(); // setter e getter per le variabili ISBN,Titolo, . String stmt="SELECT * "+ "FROM Libro "+ "WHERE ISBN='"+l.getISBN(); try { ResultSet rs=executeQuery(stmt); if (!rs.next()) // se non è gia presente lo inserisco { stmt="SELECT Cod_Genere) "+ // seleziono il codice genere dalla descrizione " FROM Genere"+ // suppongo che i generi siano precaricati nel DB " WHERE Genere.Genere="+l.getGenere(); ResultSet rs=executeQuery(stmt); rs.next(); int codGenere=rs.getInt(1); int codAutore=inserisciAutore(L.getAutore()); //inser. l’autore se manca o ricavo il codice stmt="INSERT INTO Libro (ISBN,Titolo,Editore,Anno,Cod_Autore,Cod_Genere,Prezzo)"+ " VALUES ("+l.getISBN()+","+l.getTitolo()+","+l.getEditore()+","+l.getAnno()+","+codAutore+ ","+codGenere+","+l.getPrezzo()+")"; int rc=executeUpdate(stmt); } catch(SQLException e) {System.out.println("Errore nella navigazione del ResultSet");}} closeConnection();} 47 Libreria: implementazione di aggiornaCopie public void aggiornaCopie(String ISBN,String lib,int copie) { createConnection(); // ricavo il codice libreria String stmt= "SELECT Cod_Libreria "+ "FROM Libreria "+ "WHERE Libreria.Nome="+lib; try { ResultSet rs=executeQuery(stmt); rs.next(); int codLibreria=rs.getInt(1); String stmt="UPDATE Copie SET Copie = Copie+"+copie+ " WHERE ISBN='"+ISBN+"' AND"+ " Libreria="+codLibreria; if (executeUpdate(stmt)==0) // il negozio non aveva nemmeno una copia { // inserisco una riga con il numero di copie stmt="INSERT INTO Copie ( ISBN, Libreria, Copie ) "+ "VALUES('"+ISBN+"',"+lib+","+copie+")"; int rc=executeUpdate(stmt); }} catch(SQLException e) {System.out.println("Errore nella navigazione del ResultSet");} closeConnection();} 48 Un esempio di uso della classe Libreria import java.sql.*; import java.io.*;import java.util.*; import Libreria; import Libro; import Autore; class provaJDBC{ public static void main(String args[]) throws Exception { Libreria l=new Libreria("libreria","libreria","libreria"); System.out.println(" prima dell’inserimento "); Collection c=l.ricercaPerGenere("Romanzo"); Iterator i = c.iterator(); while (i.hasNext()) { Libro libro = (Libro)i.next(); System.out.println(libro.getTitolo()+" "+ libro.getISBN()); } Autore autore=new Autore(); autore.setCognome("Pennac"); autore.setNome("Daniel"); autore.setAnnoDiNascita(1944); autore.setLuogoDiNascita("Casablanca"); 49 Un esempio di uso della classe Libreria Libro lib=new Libro(); lib.setISBN("88-07-70072-7"); lib.setTitolo("Signor Malaussene"); lib.setEditore("Feltrinelli"); lib.setAnno(1995); lib.setGenere("Romanzo"); lib.setPrezzo(20.000); lib.setAutore(autore) ; l.inserisciLibro(lib); System.out.println(" dopo l’inserimento "); c=l.ricercaPerGenere("Romanzo"); Iterator i = c.iterator(); while (i.hasNext()) { Libro libro = (Libro)i.next(); System.out.println(libro.getTitolo()+" "+ libro.getISBN()); } } } 50 Esecuzione di provaJDBC C:\jdk1.3.1_03>java provaJDBC prima dell'inserimento Lo Zen e l'arte della manutenzione della motocicletta 88-459-0734-1 Lila 88-460-0739-2 Moby Dick 88-459-1095-4 Knulp 88-459-0699-X Amicizia 88-459-0468-7 dopo l'inserimento Lo Zen e l'arte della manutenzione della motocicletta 88-459-0734-1 Lila 88-460-0739-2 Moby Dick 88-459-1095-4 Knulp 88-459-0699-X Amicizia 88-459-0468-7 Signor Malaussene 88-07-70072-7 C:\jdk1.3.1_03> 51 Impostazione della fonte dati "libreria" 1) Add di una nuova fonte dati dal Data Source Administrator 52 Impostazione della fonte dati "libreria" 2) si seleziona il Driver per Access 53 Impostazione della fonte dati "libreria" 3) si inserisce il nome della fonte dati (libreria). Si Seleziona il file libreria.mdb dal tasto "Seleziona…" e si seleziona il tasto "Avanzate …" 54 Impostazione della fonte dati "libreria" 4) si inseriscono login e password (libreria,libreria) 55