Title: Kun til bruk i tilknytning til l
1Å programmere mot en database
- Hva er JDBC? side 2Databasedrivere side
3Eksempeldatabase side 4Å få kontakt med
databasen side 5Sammenhengen mellom SQL
datatyper, Java datatyper og getxxx()-metoder si
de 6Et større eksempel side
7-8Databaseforbindelser, lage egen pool side
9-10Trelagsarkitektur, bruke poolen side
11-17Transaksjoner side 18JDBC2 side
19 Kompilerte SQL-setninger side 20
2Hva er Java Database Connectivity (JDBC)?
- JDBC er
- ikke et databasesystem, men muliggjør
kommunikasjon med et slikt - ikke et pek og klikk, dra og slipp-verktøy som
for eksempel Microsoft Access, men de som lager
slike verktøy kan bruke JDBC til å kommunisere
med databasen. - JDBC er et API som tilbyr klasser og metoder for
å sende SQL-setninger til en database, og få et
resultat tilbake. - Dette kapitlet forutsetter kjennskap til
relasjonsdatabaser og SQL.
3Databasedrivere
Java- applikasjon
Java- applikasjon
Java- applikasjon
JDBC Driver Manager
JDBC-til-ODBC- driver
Oracle-driver
Sybase-driver
ODBC-driver
En databasedriverbestår av klassersom
implementererbestemte interface.
Sybase Database
Oracle Database
Microsoft Access
Microsoft SQL Server
4Eksempeldatabase
- create table person(
- persnr integer primary key,
- fornavn varchar(30) not null,
- etternavn varchar(30) not null)
- insert into person values (100, 'OLE', 'HANSEN')
- insert into person values (101, 'ANNE GRETHE',
'ÅS') - insert into person values (102, 'JONNY',
'HANSEN')
persnr fornavn etternavn
100 OLE HANSEN
101 ANNE GRETHE ÅS
102 JONNY HANSEN
5Et eksempel på kontakt med databasen
public static void main(String args) throws
Exception String databasedriver
"oracle.jdbc.driver.OracleDriver"
Class.forName(databasedriver) // laster inn
driverklassen String databasenavn
"jdbcoraclethin_at_loiosh.stud.aitel.hist.no1521
orcl" String brukernavn showInputDialog("Br
ukernavn ") String passord
showInputDialog("Passord ") Connection
forbindelse DriverManager.getConnection(da
tabasenavn, brukernavn, passord) Statement
setning forbindelse.createStatement()
ResultSet res setning.executeQuery("select
from person") while (res.next()) int
persNr res.getInt("persnr") String
fornavn res.getString("fornavn") String
etternavn res.getString("etternavn")
System.out.println(persNr " " fornavn " "
etternavn) res.close()
setning.close() forbindelse.close()
byttes ut hvis annen databasedrivereller
database
Vår databasedriver ligger på classes111.zip.
CLASSPATH må inneholde classes111.zip.Denne
filen inneholder bl.a. oracle.jdbc.driver.OracleDr
iver.
6Sammenhengen mellom SQL datatyper, Java
datatyper og getxxx()-metoder
- CHAR,
- VARCHAR,
- LONGVARCHAR String getString()
- NUMERIC,
- DECIMAL java.math.BigDecimal getBigDecimal()
- BIT boolean getBoolean()
- TINYINT byte getByte()
- SMALLINT short getShort()
- INTEGER int getInt()
- BIGINT long getLong()
- REAL float getFloat()
- FLOAT,
- DOUBLE double getDouble()
- BINARY,
- VARBINARY,
- LONGVARBINARY byte getBytes()
- DATE java.sql.Date getDate()
- TIME java.sql.Time getTime()
- TIMESTAMP java.sql.Timestamp getTimestamp()
7Et større eksempel
Database
forbindelse Connection
finnAlle() ArrayListltPersongt endreNavn(personen
Person) boolean registrerNyPerson(fornavn
String, etternavn String) Person slettPerson(nr
int) boolean kobleNedForbindelse() void
Vis programliste 20.2 side 722-727.
8En databaseapplikasjon
Vis programliste 20.3 side 728-732.
9Databaseforbindelser er en krevende ressurs
- Her
- en bruker får tildelt en databaseforbindelse i
det han starter programmet - forbindelsen holdes fram til brukeren velger å
avslutte programmet - brukbart dersom antall brukere er relativt få
- Dersom antall brukere er mange
- en pool av databaseforbindelser
- hver henvendelse til databasen begynner med å
reservere en forbindelse som ikke holdes lenger
enn nødvendig - connection pooling en del av JDBC 2.0
- sjekk URL-Databasedrivere for drivere som
tilbyr denne tjenesten - krever at Java navne- og katalogtjeneste (JNDI)
kjører, ikke aktuelt for oss - vi lager vår egen pool
10Vår egen pool av databaseforbindelser
Forbindelse
DatabasePool
-nr -dbForb -ledig
1
-kapasitet -dbNavn -brukernavn -passord
pakke-tilgang
settLedig lukkForbindelse finnNr finnForbind
else erLedig
reserverForbindelse frigiForbindelse lukkAlleFo
rbindelser
- En databasepool består av et sett med
databaseforbindelser - Forbindelsene opprettes i konstruktøren (ikke
vist på figuren) - Forbindelsene koples ned ved kall på
lukkAlleForbindelser( ), i profesjonelle systemer
koples de ofte ned på timeout.
Vis programliste 20.4 side 734-738.
11Trelagsarkitektur
12Klienter deler databasepoolen
13Fjernobjekt som tildeler en databasewrapper
- public DbWrapperFabrikkImpl( int
poolKapasitet, String dbDriver,
String dbNavn, String brukernavn,
String passord,int startFeilkode)
throws Exception - dbPool new DatabasePool(
poolKapasitet, dbDriver, dbNavn, - brukernavn, passord)
- feilkode startFeilkode
-
- public Database lagDbWrapper()
throws RemoteException - return new DatabaseImpl(dbPool, feilkode)
-
- / Denne metoden er ikke med i interfacet, men
brukes av tjenerprogrammet / - public void stengDatabasePool()
- dbPool.lukkAlleForbindelser()
-
-
- En fabrikk tildeler databaseobjekter
- Fabrikken registreres i rmi-registeret
- Grensesnitt
- public interface DbWrapperFabrikk extends Remote
- Database lagDbWrapper() throws RemoteException
-
- Implementasjon
- public class DbWrapperFabrikkImpl extends
UnicastRemoteObject
implements DbWrapperFabrikk - private DatabasePool dbPool
- private int feilkode // brukes i
registrerNyPerson() // i klassen DatabaseImpl
14Databasewrapperen
- Grensesnitt
- public interface Database extends Remote
- ArrayListltPersongt finnAlle() throws
RemoteException - boolean endreNavn(Person personen) throws
RemoteException - Person registrerNyPerson(String fornavn, String
etternavn) throws RemoteException - boolean slettPerson(int nr) throws
RemoteException -
- Implementasjonen ligner på klassen Database (side
722ff.), men databaseforbindelser reserveres og
frigis i hver enkelt metode, se eksempel på
metode på neste lysbilde - public class DatabaseImpl extends
UnicastRemoteObject implements Database - private DatabasePool dbPool
- private int kode // Returkode fra
databasesystemet ved primærnøkkelkonflikt - public DatabaseImpl(DatabasePool startDbPool,
int startKode)
throws RemoteException - dbPool startDbPool
- kode startKode
-
15Metode som bruker databasepoolen
- Metoden ligger i klassen DatabaseImp (forts. fra
forrige lysbilde) - public ArrayListltPersongt finnAlle() throws
RemoteException - ArrayListltPersongt alle new
ArrayListltPersongt () - String sqlsetning "select persnr,
initcap(fornavn) as fn, initcap(etternavn) as en
" - "from person
order by etternavn, fornavn" - Forbindelse forbindelse null
- ResultSet res null
- Statement setning null
- try
- forbindelse dbPool.reserverForbindelse()
- setning forbindelse.finnForbindelse().crea
teStatement() - ... finner data og fyller opp
tabell-listen, se klassen Database - finally // setningene nedenfor utføres
alltid - lukkResSet(res)
- lukkSetning(setning)
- dbPool.frigiForbindelse(forbindelse.finnNr()
) - return alle
-
-
16Tjenerprogrammet
- class DatabaseTjener
- public static void main(String args) throws
Exception - String dbDriver "oracle.jdbc.driver.OracleDr
iver" - String dbNavn "jdbcoraclethin_at_baron.stud.
idb.hist.no1521orcl" - String brukernavn showInputDialog("Brukernav
n ") - String passord showInputDialog("Passord
") - int feilkode 1 // Oracle feilkode for
duplikate primærnøkkelverdier - int poolKapasitet 3
- DbWrapperFabrikkImpl db new
DbWrapperFabrikkImpl(poolKapasitet,
dbDriver, dbNavn,
brukernavn, passord, feilkode) - Naming.rebind("Persondatabase", db)
- showMessageDialog(null, "Nå
er databasepoolen oppe. Trykk Ok når den skal
stenges.") - db.stengDatabasePool() // NB!
- System.exit(0)
-
-
17De tre lagene kjører på hver sin maskin
Kompiler og kjør som forklart under figuren på
side 742.
18Transaksjoner
- En transaksjon er en logisk enhet med arbeid og
kan bestå av flere oppdateringssetninger mot
databasen. - Eksempel Dersom penger skal overføres fra én
konto til en annen er det viktig at begge
kontoene endrer saldo. Dersom en feil inntreffer
kan vi ikke risikere at bare en av kontoene har
endret saldo. - OK gjennomført transaksjon Stadfest! (commit)
- Ikke ok gjennomført transaksjone Rull tilbake!
(rollback) - Hver SQL-setning er en transaksjonsenhet.
- Interfacet Connection gir oss mulighet til å lage
transaksjoner som består av mer enn en
SQL-setning - public void setAutoCommit(boolean autocommit) //
standard er true - public void commit()
- public void rollback()
Vis programliste 20.5 side 744-745. Gjør oppgaven
side 746.
19JDBC2
- Utvidete muligheter i ResultSet
- Metoder merket 1.2 i API-dokumentasjonen (siste
avsnitt i deltaljbeskrivelsen er Since 1.2)
krever en JDBC2-driver (Oracle ojdbc14.jar) - Kan flytte deg framover og bakover.
- Kan legge inn nye rader, oppdatere data og slette
rader i databasen via resultatsettet, men
executeUpdate( ) er vanligvis mer effektivt - Mange oppdateringssetninger kan samles og sendes
til databasesystemet som en pakke (batch) - for (int nr 2001 nr lt 2010 nr)
- String sql "insert into person values(" nr
", 'Ola', 'Nordmann')" - System.out.println(sql)
- setning.addBatch(sql)
-
- int antall setning.executeBatch()
- Les mer i for eksempel http//java.sun.com/develop
er/Books/JDBCTutorial/index.html
Gjør oppgavene side 746-747.
20Kompilerte SQL-setninger
- Java-programmet sender SQL-setningen til
databasesystemet. - Databasesystemet kompilerer setningen og setter
opp en plan for mest mulig effektivt søk i
databasen. - Unødvendig å kompilere på nytt dersom bare
konstantverdier byttes ut - select from person where fornavn like Anne
and etternavn like Olsen - select from person where fornavn like Ulf and
etternavn like Hansen - Vi kan lage et ferdig kompilert setningsobjekt
ved å bruke klassen PreparedStatement. Eksempel - String sqlSetning "select from person
where fornavn like ? and etternavn like ?" - PreparedStatement setning forbindelse.prepareSt
atement(sqlSetning) - setning.setString(1, Anne) //
Søkekriteriene kan selvfølgelig leses inn, - setning.setString(2, Olsen) // se
programliste 20.6 side 748-749. - ResultSet res setning.executeQuery()
- while (res.next())
- osv.