Laboratorio di Sistemi Fondamenti di JDBC (parte2) Java Implementare l'Ereditarietà nel modello Relazionale Fig. 1 – Un semplice diagramma di classe Consideriamo il diagramma di classe della Fig. 1 (per esercizio, implementate questo diagramma UML in Java, non è difficile). Come facciamo a implementare il meccanismo dell'ereditarietà nel modello relazionale? Ci sono almeno 3 possibili soluzioni. Noi per motivi di brevità ne vedremo solo una. Possiamo “mappare” le 4 classi (Telefono, TelCellulare, TelCasa, TelUfficio) con una sola tabella e considerare pertanto il seguente schema ER: Fig. 2 – Diagramma ER Tabella TelefoniTbl TelefoniTbl jdbc-parte2.pdf IDTelefono (PK) INT (autoincremento) Numero VARCHAR Tipo VARCHAR (valori: fisso, cellulare, ufficio) PianoTariffario VARCHAR Distretto VARCHAR Interno INT IDPersona (FK) VARCHAR Pag. 1/11 Cozzetto © Laboratorio di Sistemi Fondamenti di JDBC (parte2) Java Tabella PersoneTbl PersoneTbl IDPersona (PK) VARCHAR Cognome VARCHAR Nome VARCHAR Cioè nella nostra implementazione, il campo Tipo della tabella TelefoniTbl farà da discriminatore sulla diversa tipologia di classe. Nella tabella inoltre dovranno essere presenti tutti i campi PianoTariffario, Distretto, Interno, benchè possano essere vuoti a seconda del tipo. Metadati Si possono ottenere informazioni sullo schema del database (metadati) tramite l'interfaccia DatabaseMetaData, fornendo informazioni quale il tipo di database, la versione, le istruzioni SQL ecc. L'interfaccia ResultSetMetaData fornisce informazioni sulle colonne di un ResultSet e quindi eventualmente anche sulle tabelle contenute nel database. /* * TestMetaData.java */ package classi; import import import import import import import java.sql.Connection; java.sql.DatabaseMetaData; java.sql.DriverManager; java.sql.ResultSet; java.sql.ResultSetMetaData; java.sql.SQLException; java.sql.Statement; /** * * @author maurizio */ public class TestMetaData { public static void main(String[] args) { try { Class.forName("com.mysql.jdbc.Driver"); System.out.println("Driver caricati."); } catch(ClassNotFoundException e) { System.err.println("Impossibile caricare i driver: "+e.getMessage()); return; } Connection conn = null; try { conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/biblio_db? user=root&password="); jdbc-parte2.pdf Pag. 2/11 Cozzetto © Laboratorio di Sistemi Fondamenti di JDBC (parte2) Java System.out.println("Connessione stabilita."); } catch(SQLException e) { System.err.println("Impossibile stabilire la connessione al db: "+e.getMessage()); return; } DatabaseMetaData metadata = null; try { metadata = conn.getMetaData(); } catch (SQLException e) { System.err.println("Errore generico SQL nell'acquisizione dei Metadati: "+e.getMessage()); return; } try { String driver = metadata.getDriverName() + " " + metadata.getDriverVersion(); System.out.println("Driver: "+driver); String url = metadata.getURL(); System.out.println("URL: "+url); String funzioni = metadata.getStringFunctions(); System.out.println("Funzioni supportate: "+funzioni); boolean supportaSP = metadata.supportsStoredProcedures(); boolean supportaT = metadata.supportsTransactions(); System.out.println("Supporta Stored Procedures: "+supportaSP); System.out.println("Supporta Transazioni: "+supportaT); } catch (SQLException e) { System.err.println("Errore generico SQL nell'uso dei Metadati: "+e.getMessage()); return; } try { Statement st = conn.createStatement(); String sql = "SELECT * FROM editori_tbl"; ResultSet rs = st.executeQuery(sql); ResultSetMetaData rm = rs.getMetaData(); int nCol = rm.getColumnCount(); for (int i=1; i<=nCol; i++) { String nomeColonna = rm.getColumnName(i); String tipoColonna = rm.getColumnTypeName(i); System.out.println("Nome della colonna "+i+": "+nomeColonna); System.out.println("Tipo colonna "+i+": "+tipoColonna); } } catch (SQLException e) { System.err.println("Errore generico SQL nell'uso dei Metadati: "+e.getMessage()); return; } } // fine main } // fine classe TestMetaData jdbc-parte2.pdf Pag. 3/11 Cozzetto © Laboratorio di Sistemi Fondamenti di JDBC (parte2) Java L'esecuzione produce il seguente output: Driver caricati. Connessione stabilita. Driver: MySQL-AB JDBC Driver mysql-connector-java-5.1.6 ( Revision: ${svn.Revision} ) URL: jdbc:mysql://localhost:3306/biblio_db?user=root&password= Funzioni supportate: ASCII,BIN,BIT_LENGTH,CHAR,CHARACTER_LENGTH,CHAR_LENGTH,CONCAT,CONCAT_WS,CON V,ELT,EXPORT_SET,FIELD,FIND_IN_SET,HEX,INSERT,INSTR,LCASE,LEFT,LENGTH,LOAD_FILE,LO CATE,LOCATE,LOWER,LPAD,LTRIM,MAKE_SET,MATCH,MID,OCT,OCTET_LENGTH,ORD,POSITION ,QUOTE,REPEAT,REPLACE,REVERSE,RIGHT,RPAD,RTRIM,SOUNDEX,SPACE,STRCMP,SUBSTRING, SUBSTRING,SUBSTRING,SUBSTRING,SUBSTRING_INDEX,TRIM,UCASE,UPPER Supporta Stored Procedures: true Supporta Transazioni: true Nome della colonna 1: idEditore Tipo colonna 1: INT Nome della colonna 2: nomeEditore Tipo colonna 2: VARCHAR Nome della colonna 3: indirizzoEditore Tipo colonna 3: VARCHAR Nome della colonna 4: cittaEditore Tipo colonna 4: VARCHAR BUILD SUCCESSFUL (total time: 2 seconds) Transazioni Una transazione è un insieme di operazioni che devono essere eseguite in maniera atomica, cioè o tutte le operazioni vengono eseguite con successo oppure nessuna operazione viene eseguita . Il comando SQL COMMIT fa terminare con successo una transazione , il comando SQL ROLLBACK fa abortire o terminare senza successo la transazione . Struttura di base per l'elaborazione della transazione // caricamento dei driver // .... // ottenimento della connessione conn.setAutoCommit(false); // operazioni sul database // ... // effettuiamo un SavePoint al quale possiamo tornare indietro se qualcosa va storto // (ricordiamo che le leggi di Murphy sono in agguato) :-) SavePoint sp = conn.setSavePoint(); try { // .... // conn.commit(); } catch(SQLException e) { conn.rollback(sp); } conn.setAutoCommit(true); jdbc-parte2.pdf Pag. 4/11 Cozzetto © Laboratorio di Sistemi Fondamenti di JDBC (parte2) Java Soluzione del problema posto nella prima parte Per brevità non riportiamo in questa sede la struttura della classe Autore e della classe Editore. Riportiamo invece la classe DAO e la classe Main di prova. /* * DAO.java * * Created on 7 aprile 2008, 21.20 * */ package classi; import java.util.List; import java.sql.*; import java.util.ArrayList; /** * * @author maurizio */ public class DAO { // reference al database static Connection conn; /** Creates a new instance of DAO */ public DAO() { // } // restituisce i titoli dei libri (come valori stringa) public String[] getArrayTitoli() throws SQLException { List<Libro> libri = getListaLibri(); int numLibri = libri.size(); String s[] = new String[numLibri]; int i = 0; for (Libro l : libri) { s[i] = l.getTitolo(); i++; } return s; } // fine metodo getArrayLibri() // restituisce la lista dei libri public List<Libro> getListaLibri() throws SQLException { Statement st = conn.createStatement(); List<Libro> libri = new ArrayList<Libro>(); ResultSet rs = st.executeQuery("SELECT * FROM libri_tbl, autori_tbl, editori_tbl WHERE autori_tbl.idAutore = libri_tbl.idAutore AND editori_tbl.idEditore = libri_tbl.idEditore"); jdbc-parte2.pdf Pag. 5/11 Cozzetto © Laboratorio di Sistemi Fondamenti di JDBC (parte2) Java // ciclo di lettura su tutto il RecordSet while (rs.next()) { String isbn = rs.getString("isbn"); String titolo = rs.getString("titolo"); int idAutore = rs.getInt("idAutore"); String cognome = rs.getString("cognome"); String nome = rs.getString("nome"); String nomeEditore = rs.getString("nomeEditore"); int idEditore = rs.getInt("idEditore"); // istanza di un oggetto di tipo Autore Autore a = new Autore(idAutore, cognome, nome); // istanza di un oggetto Editore Editore e = new Editore(idEditore, nomeEditore); // istanza di un oggetto di tipo Libro (scritto dall'autore a e pubblicato dalla casa editrice e) Libro l = new Libro(isbn, titolo, a, e); // caricamento nella lista libri.add(l); } rs.close(); st.close(); return libri; } // fine metodo getListaLibri() public Libro[] getArrayLibri() throws SQLException { List<Libro> elencoLibri = this.getListaLibri(); Libro[] arrayLibri = new Libro[elencoLibri.size()]; arrayLibri = elencoLibri.toArray(arrayLibri); return arrayLibri; } // fine metodo getArrayLibri() // restituisce la "collection" dei libri scritti da un determinato autore public List<Libro> getListaLibriPerAnagraficaAutore(String anagrafica) throws SQLException { Statement st = conn.createStatement(); List<Libro> libri = new ArrayList<Libro>(); ResultSet rs = st.executeQuery("SELECT * FROM libri_tbl, autori_tbl, editori_tbl WHERE autori_tbl.idAutore = libri_tbl.idAutore AND editori_tbl.idEditore = libri_tbl.idEditore AND Concat(RTrim(autori_tbl.nome),' ',RTrim(autori_tbl.cognome)) = '"+anagrafica+"'"); // ciclo di lettura su tutto il RecordSet while (rs.next()) { String isbn = rs.getString("isbn"); String titolo = rs.getString("titolo"); jdbc-parte2.pdf Pag. 6/11 Cozzetto © Laboratorio di Sistemi Fondamenti di JDBC (parte2) Java int idAutore = rs.getInt("idAutore"); String cognome = rs.getString("cognome"); String nome = rs.getString("nome"); String nomeEditore = rs.getString("nomeEditore"); int idEditore = rs.getInt("idEditore"); // istanza di un oggetto di tipo Autore Autore a = new Autore(idAutore, cognome, nome); // istanza di un oggetto Editore Editore e = new Editore(idEditore, nomeEditore); // istanza di un oggetto di tipo Libro (scritto dall'autore a e pubblicato dalla casa editrice e) Libro l = new Libro(isbn, titolo, a, e); // caricamento nella lista libri.add(l); } rs.close(); st.close(); return libri; } // fine metodo getListaLibriPerAnagraficaAutore // ritorna la collection degli autori public List<Autore> getListaAutori() throws SQLException { Statement st = conn.createStatement(); List<Autore> autori = new ArrayList<Autore>(); ResultSet rs = st.executeQuery("SELECT * FROM autori_tbl"); while (rs.next()) { int idAutore = rs.getInt("idAutore"); String cognome = rs.getString("cognome"); String nome = rs.getString("nome"); Autore a = new Autore(idAutore, cognome, nome); autori.add(a); } rs.close(); st.close(); return autori; } // fine metodo getListaAutori() // restituisce le anagrafiche degli autori public String[] getArrayAnagraficheAutori() throws SQLException { List<Autore> autori = getListaAutori(); int numAutori = autori.size(); String s[] = new String[numAutori]; int i = 0; jdbc-parte2.pdf Pag. 7/11 Cozzetto © Laboratorio di Sistemi Fondamenti di JDBC (parte2) Java for (Autore a : autori) { s[i] = a.getAnagrafica(); i++; } return s; } // fine metodo getListaAnagrafiche() public Libro getLibro(String isbn) throws SQLException { Libro l = null; // creo lo statement che rappresenta l'istruzione SQL Statement st = conn.createStatement(); // trovo gli autori dei libri ResultSet rs = st.executeQuery("SELECT * FROM libri_tbl, autori_tbl, editori_tbl WHERE autori_tbl.idAutore = libri_tbl.idAutore AND editori_tbl.idEditore = libri_tbl.idEditore AND libri_tbl.isbn = '"+isbn+"'"); if (rs.next()) { String ISBN = rs.getString("isbn"); String titolo = rs.getString("titolo"); int idEditore = rs.getInt("idEditore"); String nomeEditore = rs.getString("nomeEditore"); int idAutore = rs.getInt("idAutore"); String cognome = rs.getString("cognome"); String nome = rs.getString("nome"); //String anagrafica = rs.getString("anagrafica"); String imgUrl = rs.getString("imgUrl"); String intro = rs.getString("intro"); // istanza di un oggetto di tipo Autore Autore a = new Autore(idAutore, cognome, nome); // istanza di un oggetto Editore Editore e = new Editore(idEditore, nomeEditore); // istanza di un oggetto di tipo Libro (scritto dall'autore a e pubblicato dalla casa editrice e) l = new Libro(ISBN, titolo, imgUrl, intro, a, e); } // fine if // chiudo il ResultSet e lo statement rs.close(); st.close(); return l; } // fine metodo getLibro() // chiusura della connessione public void closeConn() throws SQLException { conn.close(); } // fine metodo closeConn() jdbc-parte2.pdf Pag. 8/11 Cozzetto © Laboratorio di Sistemi Fondamenti di JDBC (parte2) Java // caricamento dei driver e apertura della connessione al database public void openConn() throws ClassNotFoundException, SQLException { Class.forName("com.mysql.jdbc.Driver"); System.out.println("Driver caricati."); conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/biblio_db? user=root&password="); System.out.println("Connessione stabilita."); } // fine metodo openConn() } // fine classe DAO /* * Main.java */ package classi; import java.sql.SQLException; import java.util.List; /** * * @author maurizio */ public class Main { /** * @param args the command line arguments */ public static void main(String[] args) { // creazione dell'oggetto dao DAO dao = new DAO(); try { dao.openConn(); } catch (ClassNotFoundException ex) { System.out.println("Errore! Driver non caricati."); return; } catch (SQLException ex) { System.out.println("Errore! Impossibile aprire la connessione."); return; } Libro[] arrayLibri=null; try { arrayLibri = dao.getArrayLibri(); } catch (SQLException ex) { System.out.println("Errore! Impossibile caricare l'array dei libri: "+ex.getMessage()); return; } jdbc-parte2.pdf Pag. 9/11 Cozzetto © Laboratorio di Sistemi Fondamenti di JDBC (parte2) Java for (int i=0; i<arrayLibri.length; i++) System.out.println("Questo libro si intitola "+arrayLibri[i].getTitolo()+ ", il suo autore è "+arrayLibri[i].getAutore().getAnagrafica()+" e il suo editore è "+arrayLibri[i].getEditore().getNomeEditore()+"."); List<Libro> listaLibri=null; try { String anagraficaAutore = "James Gosling"; System.out.println("Lista libri scritti da "+anagraficaAutore+":"); listaLibri = dao.getListaLibriPerAnagraficaAutore(anagraficaAutore); } catch (SQLException ex) { System.out.println("Errore! Impossibile avere la lista dei libri scritti dall'autore JAmes Gosling: "+ex.getMessage()); return; } int i = 0; for (Libro l : listaLibri) { i++; System.out.println(i+". "+l.getTitolo()); } String[] anagrafiche=null; try { System.out.println("Lista autori:"); anagrafiche = dao.getArrayAnagraficheAutori(); } catch (SQLException ex) { System.out.println("Errore! Impossibile avere la lista delle anagrafiche degli autori: "+ex.getMessage()); return; } for (i=0; i< anagrafiche.length; i++) System.out.println((i+1)+". "+anagrafiche[i]); try { dao.closeConn(); System.out.println("Chiusura della connessione."); } catch (SQLException ex) { System.out.println("Impossibile chiudere la connessione: "+ex.getMessage()); return; } } //fine metodo main } // fine classe Main jdbc-parte2.pdf Pag. 10/11 Cozzetto © Laboratorio di Sistemi Fondamenti di JDBC (parte2) Java L'output della classe Main è: Driver caricati. Connessione stabilita. Questo libro si intitola 2010, l' anno del contatto, il suo autore è James Gosling e il suo editore è Apogeo. Questo libro si intitola C#: la Bibbia, il suo autore è Fabrizio Ferrari e il suo editore è Apogeo. Questo libro si intitola Java, la grande Guida, il suo autore è James Gosling e il suo editore è Apogeo. Questo libro si intitola JavaServer Pages e Servlet, il suo autore è Fabrizio Ferrari e il suo editore è Mondadori. Questo libro si intitola Java2, il Manuale Ufficiale, il suo autore è James Gosling e il suo editore è Mondadori. Questo libro si intitola 2001, a space odissey, il suo autore è Fabrizio Ferrari e il suo editore è Mondadori. Questo libro si intitola Java J2EE, il suo autore è Fabrizio Ferrari e il suo editore è Loescher. Questo libro si intitola Java: dalle basi alla programmazione avanzata, il suo autore è Fabrizio Ferrari e il suo editore è Loescher. Questo libro si intitola C++: il manuale che non cè, il suo autore è James Gosling e il suo editore è Loescher. Questo libro si intitola Pro Css and HTML Design Patterns, il suo autore è Michael Bowers e il suo editore è APress. Questo libro si intitola Pro Pay Pal E-commerce, il suo autore è Damon Williams e il suo editore è APress. Questo libro si intitola Tutorial Java, corso rapido, 4.ta edizione, il suo autore è Autori vari e il suo editore è McGraw Hill. Lista libri scritti da James Gosling: 1. 2010, l' anno del contatto 2. Java, la grande Guida 3. Java2, il Manuale Ufficiale 4. C++: il manuale che non cè Lista autori: 1. Fabrizio Ferrari 2. Giovanni Pighizzini 3. Martin Gardner 4. Martina Cozzetto 5. Maurizio Cozzetto 6. James Gosling 7. Michael Bowers 8. Damon Williams 9. Autori vari Chiusura della connessione. BUILD SUCCESSFUL (total time: 1 second) jdbc-parte2.pdf Pag. 11/11 Cozzetto ©