ݺߣ

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

More Related Content

Java 04

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