Download de presentatie
De presentatie wordt gedownload. Even geduld aub
GepubliceerdIrena de Haan Laatst gewijzigd meer dan 8 jaar geleden
1
1 JDBC Java DataBase Connectivity
2
2 Inhoud Introductie Connectie DriverManager Statement ResultSet PreparedStatement CallableStatement Mapping SQL on Java types JDBC-ODBC bridge Transacties
3
3 Introductie JDBC: platform onafhankelijke toegang tot relationele databanken via SQL De JDBC API maakt een connectie mogelijk naar een datasource, zendt queries en update statements en verwerkt resultaten
4
4 ODBC vs JDBC ODBC is gespecificeerd als een C interface gebruikt van native functies -> geen 100% pure java ODBC maakt veel gebruik van void* bron van fouten JDBC verbergt het geheugenbeheer JDBC is eenvoudiger te leren -> OO JDBC is nodig voor 100% pure java drivers voor 100% java zijn portable JDBC is gebouwd op ODBC
5
5 ODBC vs JDBC OLEDB -> low level voor developers ADO -> OO maar niet portable RDS -> vergelijkbaar met JDBC RowSet, maar niet portable UDA marketing term voor ODBC, OLEDB, ADO en RDS maar geen support voor SQL3
6
6 JDBC implementaties 2-tier applicatie, applet praat met database client/server architectuur zelfde toestel, lan, internet 3-tier eenvoudiger te beveiligen beter te beheren
7
7 JDBC software 1 the JDBC driver manager 1 included as part of the Java 2 Platform 2 the JDBC driver test suite available from the JDBC web site the JDBC-ODBC bridge included in the Solaris and Windows versions of the Java 2 Platform
8
8 Driver types 1 JDBC-ODBC bridge en ODBC driver: De Java Software bridge product voorziet in JDBC toegang via ODBC drivers. De ODBC binaire code, en meestal de database client code, moet op elke client geladen worden. Deze architectuur is best geschikt voor bedrijven waar de client installatie onder controle is. 2 Native-API partly-Java driver: Deze driver converteert JDBC calls in calls voor de API van Oracle, Sybase, Informix, IBM DB2,.... Opmerking, de operating systeem-specifieke binaire code moet geladen worden op elke client. 3 JDBC-Net pure Java driver: Deze driver converteert JDBC calls in een DBMS-onafhankelijk net protocol, die dan door de server wordt geconverteerd in het DBMS protocol. Pure Java clients kunnen zo connecteren op verschillende databases. Het protocol is afhankelijk van de leverancier. Algemeen is dit het meest flexibele alternatief voor JDBC. Meestal zijn de producten geschikt voor intranets. 4 Native-protocol pure Java driver: Deze driver converteert JDBC calls direct in een netwerk protocol dat gebruikt wordt door de DBMS-en. De client communiceert rechtstreeks met de DBMS, geschikt voor het intranet. De meeste van deze protocollen zijn proprietary, de database leveranciers leveren hun eigen drivers. De volgende zijn momenteel verkrijgbaar: Oracle, Sybase, Informix, IBM DB2, Inprise InterBase, and Microsoft SQL Server.
9
9 Het Connection object Een Connection object beheert de sessie met de server. Een applicatie kan meerdere Connection objecten hebben naar dezelfde of meerdere DBMS-en. String url = "jdbc:odbc:film"; String user = “gebruiker1”; String pwd = “pwd1” Connection con = DriverManager.getConnection(url, user, pwd); Het paswoord in de source opnemen heeft nadelen. Zelfs een jar file kan niet beveiligd worden tegen decompilatie.
10
10 De JDBC URL De algemene vorm is : : Het staat eerst en is steeds jdbc Het is naam van de driver of de naam van het databank connectiviteit mechanisme. Een voorbeeld van een sub-protocol is odbc. De sub-naam verwijst naar de ODBC-DSN. jdbc:odbc:film In dit voorbeeld, is het sub-protocol ODBC. De sub-naam film is een lokale ODBC-DSN. Deze DataSource name wordt aangemaakt via Control Panel -> Administrative Tools -> Data Sources (ODBC)
11
11 Verzenden van SQL-statements Eens de connectie is opgebouwd, kunnen commando's naar de databank worden verzonden. Alle aangeboden commando's worden verzonden. De gebruiker moet er over waken dat DBMS specifieke commando's naar de juiste DBMS gestuurd worden! Het Connection object beschikt over 3 methoden om SQL-statements te verzenden
12
12 Verzenden van SQL-statements Connection.createStatement creëert een Statement object voor het verzenden van statische SQL-statements Connection.prepareStatement creëert een PreparedStatement object. De PreparedStatement interface wordt gebruikt om precompiled statements uit te voeren. De interface heeft methoden om de IN parameters in te vullen. Connection.prepareCall creëert een CallableStatement object. De CallableStatement interface wordt gebruikt om stored procedures uit te voeren. De interface heeft bovendien methoden om de OUT en INOUT parameters in te vullen
13
13 Transactions Het Connection object beheert de transaction Default staat dit in auto-commit-mode Deze mode kan gewijzigd worden met de methode setAutoCommit(boolean) Het begin van de transactie wordt door het Connection object vastgesteld De transactie beëindigen, gebeurt met behulp van de methode commit() of rollback()
14
14 Transactions De Connection interface heeft een methode om de mate van beveiliging van transacties in te stellen. Connection.setTransactionIsolation(level) Volgende levels worden ondersteund, sommige DBMS-en kennen er nog andere. TRANSACTION_READ_UNCOMMITTED Dit niveau laat toe dat een rij wordt gewijzigd door de ene transactie, vervolgens wordt gelezen door een andere transactie zonder dat de eerste transactie is bevestigd. Dit noemt men een “dirty read”. Als de eerste transactie een rollback uitvoert heeft de tweede transactie foute data gelezen. TRANSACTION_READ_COMMITTED “Ditry reads” worden voorkomen. TRANSACTION_REPEATABLE_READ “Dirty reads” en “non-repeatable reads” worden voorkomen.Een “non-repeatable read” treedt op als tussen twee leesoperaties van een transaction de rij wordt gewijzigd en bevestigd door een tweede transactie TRANSACTION_SERIALIZABLE “Dirty reads”, “non-repeatable reads” en “phantom reads” worden voorkomen. Een “phantom read” treedt op als twee identieke selecties na elkaar een ander resultaat opleveren.
15
15 Transactions, dirty read Transaction1 begin transaction update…. rollback Transaction 2 begin transaction select …. Data is nu foutief Een dirty read treedt op wanneer data gelezen wordt tussen wijziging en een commit
16
16 Transactions, non-repeatable reads Transaction1 begin transaction select…. select…. Ander resultaat ! Transaction 2 begin transaction update …. commit Een non-repeatable read treedt op wanneer twee dezelfde lees- opdrachten een verschillende waarde opleveren
17
17 Transactions, phantom reads Transaction1 begin transaction select….where update….where Ander resultaat ! Transaction 2 begin transaction update …. commit Een phantom read treedt op wanneer twee dezelfde leesopdrachten een verschillende dataset opleveren
18
18 De DriverManager Het DriverManager object beheert de JDBC drivers Drivers registreren zichzelf bij de DriverManager als de driver wordt geladen Wanneer een connectie aanvraag gebeurt, gebruik hiervoor DriverManager.getConnection() dan test de DriverManager elke gekende driver om de verbinding op te bouwen. De eerste die reageert maakt de verbinding. De volgorde van registratie is belangrijk, - instellen van de system property jdbc.drivers -. Plaats een type 4 driver eerst, dan 3, 2 en uiteindelijk type 1.
19
19 De DriverManager Een principe voorbeeld: Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); //laad de databank driver String url = "jdbc:odbc:film"; String user = “gebruiker1”; String pwd = “pwd1” Connection con = DriverManager.getConnection(url, user, pwd); // zet een connectie op met de databank
20
20 De DriverManager import java.sql.*; public class App1 { public static void main (String args[]) { Connection con=null; String dsn =“film"; String user=""; String pwd=""; System.out.println("starting"); try { Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); con = DriverManager.getConnection("jdbc:odbc:"+dsn, user, pwd ); } catch(ClassNotFoundException cnfe) { System.out.println("jdbc-odbc driver bridge not found”); } catch(SQLException sqle) { System.out.println("connection refused to ODBC DSN”); }
21
21 De DriverManager Alle methoden van de klasse DriverManager zijn static De constructor van de klasse DriverManager is private ! Het is onmogelijk om zelf een instantie te creëeren van een DriverManager.
22
22 De Statement class Dient om een statisch SQL-statement te verzenden Een Statement object wordt gecreëerd door het uitvoeren van de methode createStatement() van een Connection object De belangrijkste methoden zijn executeQuery() executeUpdate()
23
23 Het Statement object executeQuery( String SQL-query) throws SQLException Alleen select statements ! returnt een ResultSet object
24
24 Het Statement object executeUpdate( String SQL-query) throws SQLException Alleen insert, update, delete of DDL statements ! DDL = create table, drop table, alter table,... returnt het aantal gewijzigde rijen, bij DDL statements is het aantal gewijzigde rijen steeds 0
25
25 executeQuery() try { if(con != null) { Statement s = con.createStatement(); ResultSet rs = s.executeQuery(“select * from films”); //zie voorbeeld resultset } } catch(SQLException sqle) { sqle.printStackTrace(); }
26
26 De ResultSet Een ResultSet object bevat de rijen en kolomen die voldoen aan het select statement. De data in een ResultSet is toegankelijk rij per rij. De cursor in de ResultSet geeft de huidige rij aan. De cursor wordt verplaatst met de next() methode. De standaard cursor beweegt alleen voorwaarts. Dit kan gewijzigd worden door een ander soort ResultSet in te stellen. Het standaard type is ResultSet.TYPE_FORWARD_ONLY
27
27 De ResultSet De cursor staat bij een nieuw ResultSet object vóór de eerste rij. De kolomen zijn toegankelijk met de methoden getInt(), getFloat(), getDouble(), getString(),.... Al deze methoden bestaan in 2 varianten: getType( int kolomnummer ) kolom 0 bestaat niet ! getType ( String kolomnaam ) Een ResultSet die gecreëerd is door een de parameterloze versie van createStatement() is niet aanpasbaar en kan slechts in 1 richting worden doorlopen.
28
28 De ResultSet while( rs.next() ) { System.out.println(rs.getString(1)+ ” “+rs.getString(2)); } Op deze wijze kunnen we door alle records heen lopen.
29
29 ResultSetMetaData Deze klasse bevat kolomnamen, datatypes,... van de ResultSet (metadata=gegevens over de gegevens) Gebruik ResultSet.getMetaData() om het ResultSetMetaData object te creëren. Enkele methoden: getColumnName( int kolom ) getColumnCount() getColumnClassName(int kolom ) returnt de naam van de meest geschikte java klasse om de data in op te vragen.
30
30 ResultSet en ResultSetMetaData ResultSetMetaData rsmd = rs.getMetaData(); StringBuffer resultaat = new StringBuffer(" \n \n \n"); int colCount = rsmd.getColumnCount();//start vanaf 1 !!!!! resultaat.append(" "); for(int i=1;i<=colCount;i++) { resultaat.append(" "+rsmd.getColumnName(i)+" "); } resultaat.append(" \n"); while (rs.next()) { resultaat.append(" "); for(int i=1;i<=colCount;i++) resultaat.append(" "+rs.getString(i)+" "); resultaat.append(" "); } resultaat.append(" \n \n \n"); sqlViewPane.setText(resultaat.toString()); pack(); JEditorPane contentType = text/html voor gebruik binnen HTML worden al de hier gebruikte types ingelezen als String
31
31 Lezen uit de ResultSet
32
32 Het Statement object executeUpdate( String SQL-query) throws SQLException Alleen insert, update, delete of DDL statements ! DDL = create table, drop table, alter table,... returnt het aantal gewijzigde rijen, bij DDL statements is het aantal gewijzigde rijen steeds 0
33
33 executeUpdate() Statement s = con.createStatement(); int rowCount = s.executeUpdate("update films set jaar = ‘2010’"); switch(rowCount) { case 0: JOptionPane.showMessageDialog(this,"There are no rows affected"); break; case 1: JOptionPane.showMessageDialog(this,"There's one row affected"); break; default : JOptionPane.showMessageDialog(this,"There are "+rowCount+" rows affected"); break; }
34
34 Scrollable resultSet Deze resultSet wordt veel gebruikt in combinatie met een GUI, de gebruiker heeft dan willekeurige toegang. Deze resultSet wordt gecreëerd door: Connection.createStatement(resultSetType, resultSetConcurrency); resultSetType is: TYPE_FORWARD_ONLY -> NIET GEBRUIKEN ! TYPE_SCROLL_INSENSITIVE TYPE_SCROLL_SENSITIVE resultSetConcurrency is: CONCUR_READ_ONLY CONCUR_UPDATABLE
35
35 Scrollable resultSet TYPE_SCROLL_INSENSITIVE veranderingen gemaakt door andere gebruikers, zijn niet zichtbaar TYPE_SCROLL_SENSITIVE veranderingen gemaakt door andere gebruikers, zijn wel zichtbaar Scrollen gebeurt door volgende methoden: absolute( recordnr ), relative( rows ) beforeFirst(), afterLast() next(), previous() first(), last()
36
36 Aanpasbare ResultSet Een aanpasbare resultSet wordt gecreëerd door Connection.createStatement(resultSetType, resultSetConcurrency); resultSetType is: TYPE_FORWARD_ONLY TYPE_SCROLL_INSENSITIVE TYPE_SCROLL_SENSITIVE resultSetConcurrency is: CONCUR_READ_ONLY -> NIET GEBRUIKEN ! CONCUR_UPDATABLE
37
37 Aanpasbare ResultSet Kan niet met de jdbc-odbc bridge Gebruik de updateXXX() methoden van ResultSet, zie tabel van getXXX() methodentabel van getXXX() methoden De aanpassingen in een rij worden weggeschreven d.m.v de methode UpdateRow() van ResultSet Wanneer je, je aangepaste resultaten opnieuw wil lezen, moet de resultset van het type SCROLL_SENSITIVE zijn !
38
38 Voorbeeld: DisplayAuthors We raadplegen de databank books We vragen de tabel authors op We tonen de gegevens in een JTextArea
39
39 De databank books Fig. 23.11Table relationships in books. authorISBN authorID isbn authors authorID firstName lastName publishers publisherID publisherName titles isbn title editionNumber copyright publisherID imageFile price 1 1 1
40
1 // Fig. 23.26: DisplayAuthors.java 2 // Displaying the contents of the authors table. 3 4 import java.awt.*; 5 import java.sql.*; 6 import java.util.*; 7 import javax.swing.*; 8 9 public class DisplayAuthors extends JFrame { 10 11 // JDBC driver name and database URL 12 static final String JDBC_DRIVER = "sun.jdbc.odbc.JdbcOdbcDriver"; 13 static final String DATABASE_URL = "jdbc:odbc:books"; 14 15 // declare Connection and Statement for accessing 16 // and querying database 17 private Connection connection; 18 private Statement statement; 19 20 // constructor connects to database, queries database, processes 21 // results and displays results in window 22 public DisplayAuthors() 23 { 24 super( "Authors Table of Books Database" ); 25 Importeer de package java.sql, die klassen en interfaces bevat voor de JDBC API.
41
26 27 try { 28 29 // connect to database books and query database 30 31 32 // load database driver class 33 Class.forName( JDBC_DRIVER ); 34 35 // establish connection to database 36 connection = DriverManager.getConnection( DATABASE_URL, ””, ”” ); 37 38 // create Statement for querying database 39 statement = connection.createStatement(); 40 41 // query database 42 ResultSet resultSet = 43 statement.executeQuery( "SELECT * FROM authors" ); 44 45 // process query results 46 StringBuffer results = new StringBuffer(); 47 ResultSetMetaData metaData = resultSet.getMetaData(); 48 int numberOfColumns = metaData.getColumnCount(); 49 Laad de klasse definitie voor de databank driver. De methode getColumnCount levert het aantal kolommen van de ResultSet af getMetaData() haalt de metadata op van de ResultSet Voert de query uit om alle gegevens uit de tabel authors op te halen Roept de methode createStatement aan om een object te krijgen dat de interface Statement implementeert. Laad de klasse definitie voor de databank driver.
42
50 for ( int i = 1; i <= numberOfColumns; i++ ) 51 results.append( metaData.getColumnName( i ) + "\t" ); 52 53 results.append( "\n" ); 54 55 while ( resultSet.next() ) { 56 57 for ( int i = 1; i <= numberOfColumns; i++ ) 58 results.append( resultSet.getObject( i ) + "\t" ); 59 60 results.append( "\n" ); 61 } 62 63 // set up GUI and display window 64 JTextArea textArea = new JTextArea( results.toString() ); 65 Container container = getContentPane(); 66 67 container.add( new JScrollPane( textArea ) ); 68 69 setSize( 300, 100 ); // set window size 70 setVisible( true ); // display window 71 72 } // end try 73 Creeer de GUI die de StringBuffer results toont, stel de grootte van het applicatie window en toon het applicatie window. Voeg de namen van de kolommen toe aan StringBuffer results. Voeg de gegevens van elke rij uit de ResultSet toe aan de StringBuffer results.
43
74 // detect problems interacting with the database 75 catch ( SQLException sqlException ) { 76 JOptionPane.showMessageDialog( null, sqlException.getMessage(), 77 "Database Error", JOptionPane.ERROR_MESSAGE ); 78 79 System.exit( 1 ); 80 } 81 82 // detect problems loading database driver 83 catch ( ClassNotFoundException classNotFound ) { 84 JOptionPane.showMessageDialog( null, classNotFound.getMessage(), 85 "Driver Not Found", JOptionPane.ERROR_MESSAGE ); 86 87 System.exit( 1 ); 88 } 89 90 // ensure statement and connection are closed properly 91 finally { 92 93 try { 94 statement.close(); 95 connection.close(); 96 } 97 Sluit het Statement en de databank Connection.
44
98 // handle exceptions closing statement and connection 99 catch ( SQLException sqlException ) { 100 JOptionPane.showMessageDialog( null, 101 sqlException.getMessage(), "Database Error", 102 JOptionPane.ERROR_MESSAGE ); 103 104 System.exit( 1 ); 105 } 106 } 107 108 } // end DisplayAuthors constructor 109 110 // launch the application 111 public static void main( String args[] ) 112 { 113 DisplayAuthors window = new DisplayAuthors(); 114 window.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); 115 } 116 117 } // end class DisplayAuthors
45
45 PrepareStatement De query wordt op de server gecompileerd en alleen de parameters moeten telkens worden ingevuld PrepareStatement() is aanzienlijk sneller dan het klassieke Statement() Wordt gecreërd door Connection.prepareStatement( query ) of Connection.prepareStatement( query, resultSetType, resultSetConcurrency) query is een string die een of meerdere parameters bevat in de query-string worden de parameters voorgesteld door een vraagteken die parameters worden ingevuld m.b.v. de methoden setXXX(), zie tabel van getXXX() methodentabel van getXXX() methoden
46
46 PrepareStatement i nt filmNummer = 12; preparedStatement ps = con.prepareStemement( select * from films where filmnr = ? ); ps.setInt(1, filmNummer ); rs = ps.executeQuery(); .... ps.setInt( 1, 13 ); rs = ps.executeQuery(); Parameter 1 Parameterindex
47
47 CallableStatement Hierdoor worden stored procedures uitgevoerd De query wordt op de server gecompileerd en alleen de parameters moeten ingevuld worden CallableStatement() is aanzienlijk sneller dan het klassieke Statement() Wordt gecreërd door Connection.prepareCall( query ) of Connection.prepareCall( query, resultSetType, resultSetConcurrency) query is een string die een of meerdere parameters bevat in de query-string worden de parameters voorgesteld door een vraagteken de parameters worden ingevuld m.b.v. de methoden setXXX(), zie tabel van getXXX() methoden
48
48 CallableStatement De query string bevat volgt de volgende syntax “{call ([? [,?] ])}” Een voorbeeld “{call zoekFilm(?,?)}” Het eerste vraagteken zou het jaar van de film kunnen zijn en het tweede vraagteken de naam van de regisseur van de film De parameters worden ingevuld, genummerd vanaf één tot het aanwezige aantal vraagtekens. Nadien kan de query worden uitgevoerd.
49
49 Transacties Wanneer autoCommit op true staat, worden alle statements onmiddellijk bevestigd. Wanneer een stored procedure wordt uitgevoerd, wordt elk statement op zich binnen de stored procedure bevestigd. Wanneer het laatste statement van een groep misloopt, is de database corrupt! Wanneer autoCommit op false staat, wordt automatisch een transactie gestart bij elk statement behalve commit() of rollback(). Wanneer de commit() mislukt, treedt een SQLException op, waarbij in het catch blok de rollback() plaats vindt.
Verwante presentaties
© 2024 SlidePlayer.nl Inc.
All rights reserved.