Att integrera databaser med Java Föreläsning 4- JDBC Att integrera databaser med Java
Överblick JDBC Grunderna Optimering Använda JDBC för att hantera relationsdatabaser exekvera SQL satser Ta hand om resulterande ResultSets Optimering Metadata PrepareStatement Stored Procedures Pooling Question: How many of you have the need to web-enable your database? Great, in this session, you will learn how to…. Expected background Basic knowledge of Java Servlets, JDBC and some HTML
Dagordning JDBC API & Arkitektur JDBC: Steg för steg Designmönstret Data Accessor Optimering
Vad är JDBC? JDBC Java DataBase Connectivity Enkelt att använda Portabelt Snabb utveckling och återanvändbarhet Applikation / applet DB
Java applikation/applet JDBC Arkitekturen Java applikation/applet JDBC API JDBC DriverManager JDBC Driver API JDBC Driver(s)
JDBC Arkitekturen (forts) Tre huvudkomponenter i JDBC program Java applikation/applet koden Skapad av Java utvecklaren Alla anrop till databasen enligt JDBC API:t JDBC DriverManager Tillhandahållen av JavaSoft Fungerar som länk mellan applikationen och drivrutinen JDBC drivrutinen Tillhandahållen av DB företaget eller tredje part Konverterar JDBC kod till DB specifika databaskommandon
JDBC DriverManager Hanterar kommunikationen mellan underliggande drivrutinen Kan kommunicera med vilken drivrutin som helst som följer JDBC Driver API:t JDBC DriverManager DB2 drivrutin Oracle drivrutin ... drivrutin
JDBC drivrutiner Tillhandahåller en länk mellan applikationen och den underliggande databasen/ alternativt flera underliggande databaser Följer ofta med DB eller finns även från tredje part samt medföljande exempel Man talar om fyra olika typer av drivrutiner Mixad Java och native Typ 1 och 2 Typ 1: JDBC/ODBC Bridge Driver Till 1,2 måste ladda system-specifik kod för varje klient, mest lämplig för internt bruk. 1 lite långsam eftersom man måste gå genom flera lager 3 Sidan ? I boken bra bild
JDBC Drivrutiner (forts…) Typ 2: JDBC/Native API Driver Rena Java lösningar Typ 3: JDBC Nät Protokoll Driver Typ 4: JDBC Native Protokoll Driver vendor specific protocol
JDBC API:t Det finns i dag två versioner av JDBC API JDBC 1.0 (fr.o.m. JDK 1.1) package: java.sql JDBC 2.0 (fr.o.m. JDK 1.2) två paket: java.sql och javax.sql SQL3, java istället för SQL JDBC 2.0 Standard Extension API laddas ner separat
JDBC API klasserna JDBC API:t rör sig runt fyra klasser DriverManager Connection Statement ResultSet import java.sql.*
Dagordning JDBC API & Arkitekturen JDBC: Steg för steg Designmönstret Data Accessor Optimering
JDBC: Steg för steg Steg 1: Ladda databasdrivern Steg 2: Skapa ett Connection objekt Steg 3: Skapa ett Statement och utför en “query” Steg 4: Ta hand om det resulterande ResultSet
Ladda databas Drivers Man måste alltid ha en driver för att få ett Connection objekt JDBC/ODBC bridge driver är gratis Följer med JDK 1.1 och Java 2, inte till för skarpt bruk Enkel att använda Ladda ODBC driver som heter: sun.jdbc.odbc.JdbcOdbcDriver // 1. Load the driver Class.forName(“sun.jdbc.odbc.JdbcOdbcDriver”);
JDBC: Steg för steg Steg 1: Ladda databasdrivern Steg 2: Skapa ett Connection objekt Steg 3: Skapa ett Statement och utför en “query” Steg 4: Ta hand om det resulterande ResultSet
Databas Connection Anropa getConnection(...) metoden i DriverManager klassen String dbUrl = ... String user = “speedracer”; String pass = “mark5”; Connection myConn; // 1. Load the driver Class.forName(“sun.jdbc.odbc.JdbcOdbcDriver”); // 2. Get a database connection myConn = DriverManager.getConnection( dbUrl, user, pass);
Databas URL:er URL:en bidrar med nödvändig information Generell syntax Signalerar att det är en DB URL Identifierar databasens sub-protokoll Lokaliserar databasen Generell syntax jdbc : <driverns sub-protokoll> : <db sökvägen>
Exempel på Databas URL:er ODBC Datakälla jdbc:odbc:MusicManiaDSN Oracle Databas jdbc:oracle:thin:@myServer:1721:music Sybase Databas jdbc:sybase:Tds:myServer:6689/music Informix Databas jdbc:informix-sqli://dupond.nada.kth.se: 1557/swat_test:informixserver= course_2000;user=md95-xxx;password=test Användningsexempel följer med drivrutinsförsäljarens dokumentation.
MusicMania Databasen Tabeller name id Categories artist_name title category image_name num_tracks recording_id Recordings title duration recording_id Tracks
DEMO Att angöra en ODBC brygga
Hur man använder databas URL:er exempel på uppkoppling till ODBC datakälla med namnet MusicManiaDSN String dbUrl = “jdbc:odbc:MusicManiaDSN”; String user = “speedracer”; String pass = “mark5”; Connection myConn; // 1. Load the driver Class.forName(“sun.jdbc.odbc.JdbcOdbcDriver”); // 2. Get a database connection myConn = DriverManager.getConnection(dbUrl, user, pass);
JDBC: Steg för steg Steg 1: Ladda databasdrivern Steg 2: Skapa ett Connection objekt Steg 3: Skapa ett Statement och utför en “query” Steg 4: Ta hand om det resulterande ResultSet
Statement objektet Ett Statement objekt Används för att skicka förfrågningar till databasen Skapas via factory metoden createStatement() Statement stmt = conn.createStatement() Via statement sköts exekveringen av SQL
Att ställa en SQL förfrågan: Exempel Connection myConn; Statement myStmt; ResultSet myResultSet; // 1. Load the driver Class.forName(“sun.jdbc.odbc.JdbcOdbcDriver”); // 2. Get a database connection myConn = DriverManager.getConnection(dbUrl, user, pass); // 3. create statement myStmt = myConn.createStatement(); // 4. execute query myResultSet = myStmt.executeQuery( “SELECT * FROM Recordings”);
Data Manipulation Language i JDBC JDBC stöder all standard SQL UPDATE, INSERT, DELETE genom executeUpdate(...) metoden returnerar antal berörda tupler Statement myStmt = myConn.createStatement(); int rowsAffected = myStmt.executeUpdate(“DELETE ...”);
JDBC: Steg för steg Steg 1: Ladda databasdrivern Steg 2: Skapa ett Connection objekt Steg 3: Skapa ett Statement och utför en “query” Steg 4: Ta hand om det resulterande ResultSet
ResultSet All data access skeer genom ResutSetet ResultSet har medoder för navigering i ResultSetet åtkomst av datat
Navigation genom ResultSet JDBC 1.0 tillhandahåller bara framåtgående markörer next() metod i ResultSet flyttar fram markören en rad returnera false när det inte finns några fler rader JDBC 2.0 tillhandahåller scrollbara markörer next(), previous() first(), last() beforeFirst(), afterLast() relative(n)
Navigation genom ResultSet (forts) initial position av markören markör position efter .next() .next() returnerar false här
Läsning av data-innehåll Data avläses via ett antal typbestämda getXXX metoder getInt(...) returnerar datan som en int getString(...) returnerar data som en sträng ... Vilken kolumn man ska läsa från identifieras av namn eller index index number startar på 1 String name = myRs.getString(2); cursor 1 2 3 4 ...
Ta hand om ResultSet: Exempel // create statement myStmt = myConn.createStatement(); // execute query myResultSet = myStmt.executeQuery( ... ); // process the result set while ( myResultSet.next() ) { // print the second column System.out.println(myResultSet.getString(2)); // print the column named “title” System.out.println(myResultSet.getString(“title”)); } myResultSet.close();
Hantering av SQL-problem Vad händer om tabel namnet har förändrats? JDBC Exceptions hanteras som vanliga fel. SQLException är ett exception som måste fångas. Kan ge detaljer om felets art genom metoder. getSQLState(), getMessage(), getErrorCode()
Att hantera SQL problem: exempel try { ... } catch ( SQLException exc ) { System.out.println(exc.getMessage()); System.out.println(exc.getSQLState());
JDBC: Grundläggande exempel try { Class.forName(“sun.jdbc.odbc.JdbcOdbcDriver”); myConn = DriverManager.getConnection(dbUrl, user, pass); myStmt = myConn.createStatement(); myResultSet = myStmt.executeQuery( ... ); while ( myResultSet.next() ) { System.out.println(myResultSet.getString(2)); } myResultSet.close(); catch ( SQLException exc ) { System.out.println(exc.getMessage()); catch ( ClassNotFoundException exc ) {
DEMO SQL på databasen UPDATE trade SET price = 100 WHERE buyer = ‘Tommy’;
Dagordning JDBC API & Arkitektur JDBC: Steg för steg Designmönsteret Data Accessor Optimering
Designmönstret Data Accessor Utveckla ett objekt som sköter all databashanterning. Inkappslar SQL koden Har standard metoder för data åtkomst getMusicCategories(...) getMusicRecordings(...) addRecording(...) Application MusicDataAccessor ArrayList getMusicCategories(...) ArrayList getMusicRecordings(...) void addRecording(...) DB
Dagordning JDBC API & Arkitektur JDBC: Steg för steg Designmönsteret Data Accessor Optimering
MetaData Data om data Två sorter DatabaseMetaData ResultSetMetaData dmd = conn.getMetaData(); dmd.getDatabaseProductName(); dmd.getDriverName(); ResultSetMetaData rmd = myResultSet.getMetaData(); rmd.getColumnCount();
ResultSetMetaData för igenkänning av kolumntyp Statement stmt = conn.createStatement(); if(stmt.execute(inputField.getText())) { ResultSet rs = stmt.getResultSet(); ResultSetMetaData rmd = rs.getMetaData(); while(rs.next()) { for(int i= 1; i<=rmd.getColumnCount();i++) { int typ = rmd.getColumnType(i); switch(typ) { case Types.INTEGER: print(rs.getInt(i)+" "); break; case Types.DOUBLE: print(rs.getDouble(i)+" ");
DatabaseMetaData för tabeller String[] TABLETYPES = {"TABLES"}; DatabaseMetaData dbMetaData = conn.getMetaData(); ResultSet rs = dbMetaData.getTables(null,null,null,null); System.out.print(rs); while(rs.next()) { //For every tabel String aTable = rs.getString("TABLE_NAME"); print(aTable+"\n"); ResultSet rs2 = dbMetaData.getColumns(null,null,aTable,null); while(rs2.next()) //For every column print(rs2.getString("COLUMN_NAME")+"\n");
Förberedd SQL Sats Fyra delsteg till SQL exekvering Analysera SQL satsen Kompilera SQL satsen Planering exekveringen av SQL satsen Exekvering the SQL satsen Upprepning av samma SQL erfordrar lika mycket jobb till. DB har inte alltid minne av tidigare SQL
Förberedd SQL Sats: exempel PreparedStatement extends Statement SQL satser kan förberedas Analysering, kompilering and planering vid skapelsen Exekveras senare PreparedStatement myStmt; myStmt = myConn.prepareStatement( “SELECT artist_name FROM Recordings WHERE category = ?”); ... myStmt.setString(1, “Jazz”); myRs = myStmt.executeQuery();
Stored Procedures JDBC har en CallableStatement klass Kan användas till att göra anrop till S.P. Hur att anropa S.P. från JDBC Skapa ett CallableStatement objekt Initialisera med Connection.prepareCall(...) Anropet måste vara special formaterat Omgivet av paranteser Ordet call ska vara prefix
Stored Procedures: exempel S. P. kan också skicka parametrar Samma sätt som PreparedStatements CallableStatement myStmt; myStmt = myConn.prepareCall(“{ call increasePrices( ? ) }”); ... myStmt.setDouble(1, 4.99); myRs = myStmt.executeUpdate();
Connection Pooling Uppkopplingen långsammast I stora system med många användare är det ett problem Lösningen Connection Pooling Skapa ett gäng Connection objekt Låna ut dem vid behov Effektiv i Servlet sammanhang. Skapa en vektor med Connections i init-metoden
Summering JDBC Grunderna Optimering Använda JDBC för att hantera relationsdatabaser exekvera SQL satser Ta hand om resulterande ResultSets Optimering PrepareStatement Stored Procedures Pooling
Bonus Bilder Transaktioner
Transaktions stöd När uppdatering i en tabell är beroenda av uppdateringen i en annan tabell Exempel: 100 kr ska föras över från ett konto till ett annat Två transaktioner ta bort 100 kronor från ena kontot lägg till 100 kronor på andra kontot Båda måste lyckas eller inget
Transaktions stöd (forts) Connection har en metod setAutoCommit(boolean autoCommit) try { db.setAutoCommit(false); Statement s = db.createStatement(); … s.executeUpdate(“INSERT INTO glTable VALUES(‘1001’,-100”); int tran1 = s.getUpdateCount(); s.executeUpdate(“INSERT INTO glTable VALUES(‘1002’,100”); int tran2 = s.getUpdateCount(); if((tran1 == 1) && (tran2 == 1)) { db.commit(); } else { db.rollback(); }
SQL syntax CREATE TABLE table_name ( column_name column_type column_modifiers, ..., column_name column_type column_modifiers) CREATE TABLE recordings( artist_name VARCHAR(40), title VARCHAR(40), … recording_id INT)
SQL syntax(fort...) INSERT INTO table_name(column_name, ...,column_name) VALUES (value,..., value) INSERT INTO recordings(artist_name, title, recording_id) VALUES (‘Petter’, ‘Eller hur?’, 1343)
SQL syntax (fort...) UPDATE table_name SET column_name = value, ..., column_name = value WHERE column_name = value UPDATE albums SET category = ’Crap’ WHERE year < 1980
SQL syntax (fort...) DELETE FROM table_name WHERE column_name = value DELETE FROM ablums WHERE album_id = 4 SELECT column_name,...,column_name FROM table_name WHERE colmun_name = value
Java istället för SQL Istället för att skriva: Stmt.executeUpdate(”INSERT INTO COFFEES VALUES(’NÄSKAFFE’, 150,10.99)”); conn.createStatement( ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet uprs = stmt.executeQuery(”Select *...
Java istället för SQL (fort...) uprs.movetToInsertRow(); uprs.updateString(”COF_NAME”,”Näskaffe”); uprs.updateInt(”SUP_ID”,150); uprs.updateFloat(”PRICE”,10.99); uprs.insertRow(); Resurser http://www.javasoft.com/products/jdbc http://www.javasoft.com/docs/books/tutorial/jdbc