Java 04

download Java 04

If you can't read please download the document

Transcript of Java 04

Diapositiva 1

Java

JDBCAccesso al database

Davide [email protected]

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 = canideNome = polly descrizione = uccelloNome = silvestro descrizione = felinoNome = 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

03/03/09