Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Java 04

2,206 views

Published on

Introduzione all'uso di JDBC

Published in: Technology
  • Be the first to comment

Java 04

  1. 1. Java JDBC Accesso al database Davide Ficano [email_address]
  2. 2. Cosa è JDBC <ul><li>JDBC significa Java Database Connectivity </li></ul><ul><ul><li>Standard definito da Sun MicroSystems per connettere programmi Java ai database relazionali </li></ul></ul><ul><ul><li>E' costituito da un insieme di classi e interfacce scritte in Pure Java </li></ul></ul><ul><ul><li>Si basa sul concetto di driver di database </li></ul></ul><ul><ul><li>Il driver è una implementazione JDBC specifica per database </li></ul></ul><ul><ul><li>Permette ai diversi fornitori di database di estendere lo standard con i loro specifici driver JDBC (Oracle, MySQL, MS SQL Server) </li></ul></ul>
  3. 3. Cosa fa JDBC <ul><li>Stabilisce una connessione con il database </li></ul><ul><li>Invia comandi SQL </li></ul><ul><li>Processa il risultato </li></ul>
  4. 4. Come si usa JDBC <ul><li>Import dei package java.sql.* </li></ul><ul><li>Registrazione del driver (Oracle, MySQL) </li></ul><ul><li>Apertura connessione </li></ul><ul><li>Creazione oggetto Statement </li></ul><ul><li>Esecuzione query e recupero dati dal ResultSet </li></ul><ul><li>Utilizzo ResultSet </li></ul><ul><li>Chiusura risorse ResultSet e Statement </li></ul><ul><li>Chiusura connessione </li></ul>
  5. 5. I passi da eseguire DriverManager Driver Connection Statement ResultSet
  6. 6. JDBC Registrazione Driver <ul><li>Per utilizzare un driver di database un'applicazione lo deve rendere disponibile applicazione (si chiama registrazione del driver) </li></ul><ul><li>Questo si fa ad esempio come prima istruzione del metodo main </li></ul>public static void main(String[] args) throws Exception { Class. forName ( JDBC_DRIVER ).newInstance(); ... ... } <ul><ul><li>Nell'esempio JDBC_DRIVER e' un stringa contenente il nome del driver </li></ul></ul>
  7. 7. JDBC Apertura connessione /1 <ul><li>La classe java.sql.DriverManager permette di creare connessioni </li></ul><ul><li>I metodi per creare una connessione sono </li></ul><ul><ul><li>getConnection(String url, String user, String password) throws SQLException </li></ul></ul><ul><ul><ul><li>Tenta di stabilire una connessione tramite una URL utilizzando user e password </li></ul></ul></ul><ul><ul><li>getConnection(String url) throws SQLException </li></ul></ul><ul><ul><ul><li>Tenta di stabilire una connessione tramite una URL </li></ul></ul></ul><ul><li>L'overload del metodo con un solo paramentro permette di passare user e password direttamente sulla URL </li></ul><ul><li>Tutti i metodi di JDBC lanciano l'eccezione java.sql.SQLException </li></ul>
  8. 8. JDBC Apertura connessione /2 <ul><li>Una connessione rappresenta una sessione con uno specifico db </li></ul><ul><ul><li>Le sessioni sono risorse preziose in un db e bisogna gestirle con cura </li></ul></ul><ul><li>Si possono avere può connessioni contemporanee con il db </li></ul><ul><li>E' possibile ottenere informazioni sulla struttura del db (metadata) </li></ul><ul><li>E' possibile gestire le transazioni </li></ul><ul><li>In JDBC spesso si usano i connection pool per ottimizzare gli accessi alle connessioni </li></ul>
  9. 9. La URL JDBC <ul><li>La URL contiene varie informazioni </li></ul><ul><ul><li>macchina (e porta) dove gira il database </li></ul></ul><ul><ul><li>nome dell'istanza del database </li></ul></ul><ul><li>Cambia per ogni database (Oracle, MySQL) </li></ul><ul><ul><li>jdbc:oracle:thin:[user/password]@[host][:port]:SID </li></ul></ul><ul><ul><li>jdbc:mysql://[host]:[po]/[dbname] </li></ul></ul><ul><li>Viene usato lo pseudo protocollo jdbc: </li></ul>
  10. 10. Eseguire uno statement <ul><li>Il codice mostrato </li></ul><ul><ul><li>ottiene una connessione ad database (linea 2) </li></ul></ul><ul><ul><li>esegue uno statement di select (linea 5) </li></ul></ul><ul><li>public void eseguiSelect() throws SQLException { </li></ul><ul><li>Connection conn = DriverManager </li></ul><ul><li>. getConnection ( JDBC_URL , JDBC_USER , JDBC_PASSWORD ); </li></ul><ul><li>Statement st = conn.createStatement(); </li></ul><ul><li>st.executeQuery( &quot;select * from Animale&quot; ); </li></ul><ul><li>st.close(); </li></ul><ul><li>conn.close(); </li></ul><ul><li>} </li></ul>
  11. 11. Interfaccia java.sql.Statement <ul><li>Viene usato il metodo Connection.createStatement per </li></ul><ul><ul><li>ottenere una interfaccia JDBC per eseguire istruzioni SQL statiche </li></ul></ul><ul><ul><li>Una istruzione si dice statica quando non ci sono variabili JDBC che modificano la query </li></ul></ul><ul><li>st.executeQuery( &quot;select * from Animale where nome = 'Fido'&quot; ); </li></ul><ul><ul><li>La condizione di where è statica se il nome cambia dovrei costruire la query in modo diverso, ad esempio concatenando la stringa </li></ul></ul><ul><li>st.executeQuery( &quot;select * from Animale where nome = '&quot; + nome + &quot;'&quot; ); </li></ul>
  12. 12. Alcuni metodi dell'interfaccia java.sql.Statement <ul><li>execute(String sql) </li></ul><ul><ul><li>Esegue una espressione SQL che può ritornare risultati multipli </li></ul></ul><ul><li>executeQuery(String sql) </li></ul><ul><ul><li>Esegue una espressione SQL che ritorna un solo oggetto ResultSet </li></ul></ul><ul><li>executeUpdate(String sql) </li></ul><ul><ul><li>Esegue una espressione SQL che può essere: INSERT, UPDATE, or DELETE </li></ul></ul><ul><li>Perché tutti questi metodi così simili? </li></ul><ul><ul><li>Per sfruttare le ottimizzazioni del database </li></ul></ul><ul><ul><li>il programmatore sa cosa vuole e richiama il metodo più appropriato </li></ul></ul>
  13. 13. Interfaccia java.sql.ResultSet <ul><li>Un ResultSet fornisce l'accesso ai dati di una tabella generati eseguendo uno Statement </li></ul><ul><li>Si può aprire un solo ResultSet alla volta </li></ul><ul><li>Il ResultSet mantiene un cursore alla riga corrente ottenuta dal database </li></ul>
  14. 14. Alcuni metodi di java.sql.ResultSet <ul><li>java.sql.Date getDate(int columnIndex) </li></ul><ul><li>double getDouble(int columnIndex) </li></ul><ul><li>int getInt(int columnIndex) </li></ul><ul><li>String getString(int columnIndex) </li></ul><ul><li>Il parametro in ingresso, columnIndex, indica la posizione del campo nella select </li></ul><ul><li>E' possibile passare il nome del campo anziché la posizione </li></ul><ul><li>java.sql.Date getDate(String columnName) </li></ul>
  15. 15. Chiusura risorse <ul><li>Si e' detto che le connessioni sono risorse preziose per cui vanno rilasciate appena possibile </li></ul><ul><li>Lo stesso vale per Statement e ResultSet </li></ul><ul><li>La chiusura avviene utilizzando il metodo close() </li></ul><ul><ul><li>Connection.close() </li></ul></ul><ul><ul><li>Statement.close(); </li></ul></ul><ul><ul><li>ResultSet.close(); </li></ul></ul>
  16. 16. Esempio di select completo <ul><li>private void stampaNomi(Connection conn) throws SQLException { </li></ul><ul><li>String query = &quot;select nome from Animale order by nome&quot;; </li></ul><ul><li>Statement st = conn.createStatement(); </li></ul><ul><li>ResultSet rs = st.executeQuery( query ); </li></ul><ul><li>while (rs.next()) { </li></ul><ul><li>String nome = rs.getString( &quot;nome&quot; ); </li></ul><ul><li>System. out .println( &quot;Nome = &quot; + nome); </li></ul><ul><li>} </li></ul><ul><li>rs.close(); </li></ul><ul><li>st.close(); </li></ul><ul><li>} </li></ul>
  17. 17. Esercizio /1 SELECT JDBC <ul><li>Sul database sono presenti due tabelle gia' popolate </li></ul><ul><li>Scrivere un programma che </li></ul><ul><ul><li>stampi i nomi ed il tipo di animale uno per riga </li></ul></ul><ul><li>L'output atteso e' mostrato in Figura </li></ul>Nome = fido descrizione = canide Nome = polly descrizione = uccello Nome = silvestro descrizione = felino Nome = titty descrizione = uccello
  18. 18. Non solo select /1 Statement.executeUpdate <ul><li>Quando si vuole eseguire una INSERT su database si deve usare executeUpdate </li></ul><ul><li>private void inserisciCavalli(Connection conn) throws SQLException { </li></ul><ul><li>Statement st = conn.createStatement(); </li></ul><ul><li>st.executeUpdate( &quot;insert into animale (nome, fk_tipo) values ('furia', 'cavallo');&quot; ); </li></ul><ul><li>st.executeUpdate( &quot;insert into animale (nome, fk_tipo) values ('fulmine', 'cavallo');&quot; ); </li></ul><ul><li>st.close(); </li></ul><ul><li>} </li></ul>
  19. 19. Non solo select /2 executeUpdate <ul><li>executeUpdate viene usato anche per UPDATE e DELETE </li></ul><ul><li>E' possibile conoscere quanti record sono stati interessati dall'operazione di UPDATE/DELETE utilizzando il valore ritornato </li></ul><ul><li>private void eliminaCavalli(Connection conn) throws SQLException { </li></ul><ul><li>Statement st = conn.createStatement(); </li></ul><ul><li>int count; </li></ul><ul><li>count = st.executeUpdate( &quot;delete from animale where fk_tipo = 'cavallo'&quot; ); </li></ul><ul><li>System. out .println(String. format ( &quot;Eliminati %d cavalli&quot; , count)); </li></ul><ul><li>st.close(); </li></ul><ul><li>} </li></ul>
  20. 20. Esercizio /2 UPDATE JDBC <ul><li>Scrivere un programma che permetta di rinominare un animale </li></ul><ul><li>Il metodo renameAnimale deve prendere 4 argomenti </li></ul><ul><ul><li>connessione </li></ul></ul><ul><ul><li>nuovo nome </li></ul></ul><ul><ul><li>vecchio nome </li></ul></ul><ul><ul><li>tipo animale </li></ul></ul><ul><li>Stampare un messaggio che indichi se l'operazione ha avuto successo </li></ul><ul><li>Quando l'operazione ha avuto successo? </li></ul>
  21. 21. Indipendenza dal database /1 <ul><li>Le query che abbiamo visto contengono le stringhe che intendiamo usare </li></ul><ul><ul><li>nelle clausole WHERE </li></ul></ul><ul><ul><li>nei valori delle INSERT </li></ul></ul><ul><li>Ma cosa succede se le stringhe hanno caratteri particolari? Ad esempio apici o doppie virgolette </li></ul>
  22. 22. Indipendenza dal database /2 <ul><li>La soluzione e' quella di fare l'escape ma </li></ul><ul><ul><li>questo e' un compito oneroso per il programmatore </li></ul></ul><ul><ul><li>ogni database ha regole diverse </li></ul></ul><ul><ul><ul><li>Oracle usa gli apici per definire una stringa </li></ul></ul></ul><ul><ul><ul><li>MySql usa anche le doppie virgolette </li></ul></ul></ul>&quot;select * from Animale where nome = '&quot; + nome + &quot;'&quot; &quot;delete from animale where fk_tipo = 'cavallo'&quot; &quot;insert into animale (nome, fk_tipo) values ('furia', 'cavallo');&quot;
  23. 23. Indipendenza dal database /3 <ul><li>Il lavoro di escape deve essere fatto dal driver JDBC </li></ul><ul><ul><li>Ogni driver conosce le proprie regole (Oracle sa come fare l'escape delle proprie stringhe) </li></ul></ul><ul><ul><li>le differenze non riguardano solo le stringhe, possono coinvolgere anche </li></ul></ul><ul><ul><ul><li>numeri interi </li></ul></ul></ul><ul><ul><ul><li>numeri in virgola mobile </li></ul></ul></ul><ul><ul><ul><li>ma soprattutto le date (ogni database ha un suo formato per definire una data ad esempio in una clausola WHERE) </li></ul></ul></ul><ul><ul><li>Il codice di accesso al DB viene scritto una sola volta </li></ul></ul>
  24. 24. Indipendenza dal database /3 Connection.PreparedStatement <ul><li>Per risolvere il problema e' sufficiente utilizzare la classe PreparedStatement al posto di Statement </li></ul><ul><li>Non si usa il metodo Connection.createStatement ma Connection.prepareStatement </li></ul><ul><li>I valori da associare vengono sostituiti con il carattere punto interrogativo </li></ul><ul><li>Per impostare i parametri si usano i metodi </li></ul><ul><ul><li>setString / setDate / setXXX </li></ul></ul>
  25. 25. Indipendenza dal database /4 Connection.PreparedStatement <ul><li>Differenze di codifica tra createStatement... </li></ul><ul><li>String sql = &quot;select a.nome from ANIMALE a, TIPO_ANIMALE t&quot; </li></ul><ul><li>+ &quot; where a.fk_tipo=t.tipo&quot; </li></ul><ul><li>+ &quot; and t.tipo=?&quot; ; // con ? si definisce un parametro </li></ul><ul><li>PreparedStatement st = conn.prepareStatement(sql); // riceve la query </li></ul><ul><li>st.setString(1, tipoAnimale); </li></ul><ul><li>ResultSet rs = st.executeQuery(); </li></ul><ul><li>String sql = &quot;select a.nome from ANIMALE a, TIPO_ANIMALE t&quot; </li></ul><ul><li>+ &quot; where a.fk_tipo=t.tipo&quot; </li></ul><ul><li>+ &quot; and t.tipo='&quot; + tipoAnimale + &quot;'&quot; ; </li></ul><ul><li>Statement st = conn.createStatement(); </li></ul><ul><li>ResultSet rs = st.executeQuery(sql); // executeQuery riceve la query </li></ul><ul><li>... e prepareStatement </li></ul>
  26. 26. Esercizio /3 Utilizzare PreparedStatement <ul><li>Modificare il codice di renameAnimale in modo che funzioni con PreparedStatement </li></ul>
  27. 27. Oggetti VO e DAO <ul><li>La scrittura di codice java per l'accesso al database e' stata razionalizzata dividendo logicamente il codice </li></ul><ul><li>Vengono create due gerarchie di classi contenenti </li></ul><ul><ul><li>Oggetti che rappresentano la struttura della tabella </li></ul></ul><ul><ul><li>Oggetti che effettuano SELECT/INSERT/UPDATE/DELETE </li></ul></ul><ul><li>Questa classificazione non e' obbligatoria ma agevola la suddivisione in gerarchie ben definite </li></ul>
  28. 28. Oggetti VO /1 Value Object <ul><li>Un value object e' una rappresentazione Java di una tabella </li></ul><ul><li>Per la tabella ANIMALE esistera' la classe Animale </li></ul><ul><li>Per la tabella TIPO_ANIMALE esistera' la classe TipoAnimale </li></ul><ul><li>Le classi altro non sono che dei bean con getter e setter (non hanno logica) </li></ul>
  29. 29. Oggetti VO /2 Value Object <ul><li>public class Animale { </li></ul><ul><li>private String nome ; </li></ul><ul><li>private String tipo ; </li></ul><ul><li>public String getNome() { </li></ul><ul><li>return nome ; </li></ul><ul><li>} </li></ul><ul><li>public void setNome(String nome) { </li></ul><ul><li>this . nome = nome; </li></ul><ul><li>} </li></ul><ul><li>public String getTipo() { </li></ul><ul><li>return tipo ; </li></ul><ul><li>} </li></ul><ul><li>public void setTipo(String tipo) { </li></ul><ul><li>this . tipo = tipo; </li></ul><ul><li>} </li></ul><ul><li>} </li></ul>
  30. 30. Oggetti DAO /1 Data Access Object <ul><li>Queste classi interagiscono con il database e utilizzano i VO </li></ul><ul><li>La connessione viene passata al costruttore oppure ai singoli metodi </li></ul><ul><li>Per la tabella ANIMALE esistera' una classe AnimaleDAO </li></ul><ul><li>L'output di un DAO (se presente) dovrebbe essere sempre del tipo della tabella che rappresenta </li></ul><ul><li>Eventuali JOIN tra piu' tabelle diventano dettagli implementativi </li></ul>
  31. 31. Oggetti DAO /2 Data Access Object <ul><li>public class AnimaleDAO { </li></ul><ul><li>public List ricercaByTipo(Connection conn, String tipoAnimale) </li></ul><ul><li>throws SQLException { </li></ul><ul><li>... // il codice che crea il PreparedStatement e' stato omesso </li></ul><ul><li>List list = new ArrayList(); </li></ul><ul><li>while (rs.next()) { </li></ul><ul><li>Animale a = new Animale(); </li></ul><ul><li>a.setNome(rs.getString(1)); </li></ul><ul><li>a.setTipo(tipoAnimale); </li></ul><ul><li>list.add(a); </li></ul><ul><li>} </li></ul><ul><li>return list; </li></ul><ul><li>} </li></ul><ul><li>} </li></ul>
  32. 32. Esercizio /4 VO e DAO <ul><li>Creare gli oggetti VO e DAO per Animale </li></ul><ul><li>Creare i metodi utilizzando il pattern VO/DAO per </li></ul><ul><ul><li>Cercare per nome e per tipo </li></ul></ul><ul><ul><li>Inserire un nuovo animale </li></ul></ul><ul><ul><li>Rinominare un Animale </li></ul></ul><ul><ul><li>Cancellare un Animale </li></ul></ul>

×