Java DataBase Connectivity

Slides:



Advertisements
Verwante presentaties
KINN 2010 •OOP •O Object •O Georiënteerd •P Programmeren.
Advertisements

Evaluatie van MS Exchange 2000 en opzetten van een server voor wereldwijde uitwisseling van projectinformatie Bertels David 3ICT1 Stageplaats: Acros Organics.
Module 7 – Hoofdstuk 5 (1) SQL – een begin.
Installatie & beheer Jonathan Mohnen Martijn Wolfs.
Deel XIV Eerste echte e-commerce applicatie Implementatie (vervolg) 1 Internetapplicaties Deel 14: Eerste echte e-commerce applicatie: Implementatie (vervolg)
PHP & MYSQL LES 03 PHP & DATABASES. PHP & MYSQL 01 PHP BASICS 02 PHP & FORMULIEREN 03 PHP & DATABASES 04 CMS: BEST PRACTICE.
Ronde (Sport & Spel) Quiz Night !
Instructie Programmeren Task 8 5JJ70. PAGE 2 Task 8: Double Linked List Het doel van deze opdracht is: Het opbouwen van een tweetal klassen, die samen.
Hogeschool van Amsterdam - Interactieve Media – Internet Development – Jochem Meuwese - -
Van domeinklasse tot implementatie
Hogeschool van Amsterdam - Interactieve Media – Internet Development – Jochem Meuwese - -
Base: bewerkingen 2 soorten - Oplopend- Aflopend.
Het ontwerpen van een klasse
Greenfoot Workshop Bobby - Snake.
Hoofdstuk 6: Controle structuren
Computervaardigheden en Programmatie Universiteit AntwerpenDatabank - Basis 4.1 Computervaardigheden en Programmatie 1rste BAC Toegepaste Biologische Wetenschappen.
Inleiding Informatica Prof. Dr. O. De Troyer Hoofdstuk 10: Omgaan met problemen.
HANDLEIDING: REGISTREREN VAN VACCINATIES Q-KOORTS
Download en installeer de gereedschappen
Hogeschool van Amsterdam - Interactieve Media – Internet Development – Jochem Meuwese - -
Opleiding ICT © J.W. Jonker Dia 1/20 Systemen Besturingssoftware Windows XP Mark van Heck.
1 Voorwaarden hergebruik Modulair ontwerp Low coupling High cohesion.
JAVA -- H51 CONSTRUCTOR –- COPY-CONSTRUCTOR 1Constructor: Dezelfde naam als de klasse Wordt uitgevoerd d.m.v. new Initialisatie van de (private) attributen.
Werken aan Intergenerationele Samenwerking en Expertise.
Hibernate Object relational mapping
Workshop PHP Een productencatalogus Met database.
Algoritmiek Object-georiënteerd Programmeren
6.1 Inleiding HOOFDSTUK 6 METHODEN
Dia 1 Productencatalogus: technische sessie Samen beter informeren.
Presenteert:.
Deel 9: Relationele Databases: Oef. & 1e client- server app 1 Internetapplicaties Deel 9: Relationele Databases: Oefeningen en 1e client- serverapplicatie.
Deel XIII Eerste echte e-commerce applicatie (iteraties + impl ) 1 Internetapplicaties Deel 13: Eerste echte e-commerce applicatie: Enkele iteraties met.
OO Analyse in de praktijk OO Analyse in de praktijk IV OO basisregels.
Herhaling Java-programmatie en geautomatiseerd testen (vervolg)
Deel X: JSP + Java + database 1 Internetapplicaties Deel 10: JSP + Java + database: Client Server via http.
1 Syntax JavaLogo. 2 Hoofdstuk 1 Tekenen in Java.
De financiële functie: Integrale bedrijfsanalyse©
1 Zie ook identiteit.pdf willen denkenvoelen 5 Zie ook identiteit.pdf.
SQL ( SERVER ) Les #02: T-SQL. A GENDA Herhaling les 4 Views SELECT…INTO Beheren van tabellen: CREATE ALTER DROP Opdracht voor de volgende les.
Introductie tot GoF patterns in Java
Computervaardigheden Hoofdstuk 4 — Databank (Basis)
Datacommunicatie en netwerken
Tircms03-p les 4 Klassen. Abstracte datatypes in C struct stack { char info[100]; int top; }; void reset(stack *s) { s->top = -1; } void push(stack *s,
JAVA: een platformonafhankelijke taal
Datamodellering en –verwerking 8C020 college 9. Terugblik college week 8 Terugkoppeling opdracht deel A Toepassingen van Petri-netten in biologie Oefeningen.
Vakgroep Telecommunicatie en Informatieverwerking 1 Toegangsmogelijkheden voor applicaties Hoofdstuk 8 Database, Document and Content Management.
Databases Hoofdstuk 25 Hoofdstuk 24.
2 August SQL Les August Agenda Herhaling Herhaling Cursors Cursors MS SQL Server and MS Excel MS SQL Server and MS Excel Oefeningen.
LVNL architectuur (gevalideerd datamodel met opvraagbare queries)
Java Objectgeoriënteerd Programmeren in Java met BlueJ
ANALYSE 3 INFANL01-3 WEEK CMI Informatica.
BIMAIV03 Les A1 BIMAIV03 Les A1 Databases. De gegevens in een database vormen de grondstof voor informatie De informatie wordt opgevraagd in de taal met.
Week 6 BIMAIV03 les B1. DML en DDL ata D anipulation M anguage L ata D efinition D anguage L.
 C++ heeft een inheritance mechanisme  Manier om functionaliteit te ‘erfen’ van een parrent class ◦ Polymorphisme ◦ Zoals we het ook in C# kennen.
Java & het Web Programma: Databases (jdbc, JNDI, ORM, JPA)
1 JDBC Java DataBase Connectivity. 2 Inhoud Introductie Connectie DriverManager Statement ResultSet PreparedStatement CallableStatement Mapping SQL on.
Wat is SQL (1)? SQL (Structured Query Language):  is een zeer krachtige taal met een beperkt vocabulaire (aantal ‘woorden’)  is declaratief (‘WAT’ niet.
De definitie van een object. Een object is een verzameling van eigenschappen en bewerkingen. Veel voorkomende objecten zijn: D (display) Gui (user interface)
Software Development fundamentals
OOS Object geOrienteerd Software-ontwerp - 5
Software Development fundamentals
Software Development fundamentals
SQL Les February 2019.
SQL Les 7 24 February 2019.
SQL Les 1 5 April 2019.
SQL Les 6 14 April 2019.
SQL Les 9 12 May 2019.
SQL Les May 2019.
Software Development fundamentals
Software Development fundamentals
Transcript van de presentatie:

Java DataBase Connectivity JDBC Java DataBase Connectivity

Introductie JDBC: platform onafhankelijke toegang tot relationele databanken via SQL De JDBC API maakt een connectie naar een datasource mogelijk, zendt queries en update statements en verwerkt resultaten JDBC is gebouwd op ODBC

JDBC implementatie

Driver types

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.

Basisstappen: De 4 basisstappen: Registeren van een databasedriver Connectie met een databank maken Creatie van een Statement object Uitvoeren van een query, een update, …

Registreren van databasedriver De databasedriver registreren kan door het manueel laden van de klasse met Class.forName(“drivernaam”); Bij gebruik van de JDBC-ODBC Bridge driver, wordt dit: Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");

Connectie met databank maken Een Connection object beheert de sessie met de server Connection con = DriverManager.getConnection(url, "myLogin","myPassword"); Voorbeeld: String url = "jdbc:odbc:film"; String user = “gebruiker1”; String pwd = “pwd1”; Connection con = DriverManager.getConnection(url, user, pwd);

De connectie De JDBC URL is de URL voor de databank De algemene vorm is <protocol>:<sub-protocol>:<sub-naam> Het <protocol> staat eerst en is steeds jdbc Het <sub-protocol> 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. De sub-naam film is een lokale ODBC-DSN.

Data Source Name Deze DataSource name wordt aangemaakt in Windows 2000 via Control Panel -> Administrative Tools -> Data Sources (ODBC). In Windows XP via configuratiescherm -> prestaties en onderhoud -> systeembeheer -> gegevensbronnen (ODBC): selecteer Microsoft Access Driver, geef de locatie & naam van de databank (via knop selecteren), vb films.mdb en vul een naam (voor dit voorbeeld films) in bij naam van de gegevensbron. Onder deze naam zal de ODBCdriver-koppeling bereikbaar zijn vanuit de JAVA code. Je kan de ODBC registratie automatisch laten gebeuren door bij de URL een extra parameter door te geven: “jdbc:odbc:MS Access-database;DBQ=film”

De connectie String user De database logon ID String pwd De database logon wachtwoord De connectie is een open connectie die je kan gebruiken om JDBC statements te maken die SQL opdrachten doorsturen naar de DBMS

De DriverManager DriverManager beheert de JDBC drivers Drivers registreren zichzelf bij de DriverManager als de driver wordt geladen Wanneer een connectie aanvraag gebeurt, dan test de DriverManager elke gekende driver om de verbinding op te bouwen. De eerste die reageert maakt de verbinding. Alle methoden van de klasse DriverManager zijn static De constructor van de klasse DriverManager is private!

Voorbeeld: 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”);

Verzenden van SQL-statements Eens de connectie is opgebouwd, kunnen commando's naar de databank worden verzonden. Het Connection object beschikt over 3 methoden om SQL- statements te verzenden: createStatement creëert een Statement object voor het verzenden van statische SQL-statements 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. 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

Het Statement object 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 argumenten van connection.createStatement(): public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException resultSetType TYPE_FORWARD_ONLY: cursor kan enkel voorwaarts bewegen TYPE_SCROLL_INSENSITIVE: cursor kan in beide richtingen bewegen. Wijzigingen in de database worden pas merkbaar nadat de query opnieuw wordt geactiveerd. TYPE_SCROLL_SENSITIVE: cursor kan in beide richtingen bewegen. Wijzigingen in de database worden direct merkbaar. resultSetConcurrency CONCUR_READ_ONLY: de resultSet kan de database niet wijzigen CONCUR_UPDATABLE: de resultSet kan de database wijzigen

Het Statement object De belangrijkste methoden zijn executeQuery() executeUpdate()

Het Statement object throws SQLException Alleen select statements ! ResultSet executeQuery( String SQL-query) throws SQLException Alleen select statements ! returnt een ResultSet object

Het Statement object int 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

Het Statement object ResultSetMetaData getMetaData() throws SQLException

Voorbeeld: executeQuery() try { if(con != null) { Statement s = con.createStatement(); ResultSet rs = s.executeQuery(“select * from films”); //zie verderbij voorbeeld resultset } } catch(SQLException sqle) { sqle.printStackTrace(); }

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

De ResultSet De cursor staat bij een nieuw ResultSet object vóór de eerste rij. De kolomen zijn toegankelijk met de methode getObject() of met de specifieke 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.

Voorbeeld: ResultSet while ( rs.next() ) { System.out.println(rs.getString(1)+ ” “+rs.getString(2)); } Op deze wijze kunnen we door alle records lopen

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.

Voorbeeld: ResultMetaDataSet ResultSetMetaData rsmd = rs.getMetaData(); StringBuffer resultaat = new StringBuffer("<HTML>\n<BODY>\n<TABLE BORDER=10>\n"); int colCount = rsmd.getColumnCount(); //start vanaf 1 !!!!! resultaat.append("<TR>"); for(int i=1;i<=colCount;i++) { resultaat.append("<TH>"+rsmd.getColumnName(i)+"</TH>"); } resultaat.append("</TR>\n"); while (rs.next()) resultaat.append("<tr>"); resultaat.append("<td>"+rs.getString(i)+"</td>"); resultaat.append("</tr>"); resultaat.append("</TABLE>\n</BODY>\n</HTML>\n"); sqlViewPane.setText(resultaat.toString()); voor gebruik binnen HTML worden al de hier gebruikte types ingelezen als String JEditorPane contentType = text/html

Lezen uit de ResultSet

Exception handling De code moet in een try catch blok staan. Mogelijke exceptions zijn: SQLException Bij interactie met de databank ClassNotFoundException Als de driver niet gevonden wordt In een finally blok geven we de resources vrij die eveneens weer een SQLException kunnen gooien: s.close(); c.close();

Voorbeeld: 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"); default : JOptionPane.showMessageDialog(this,"There are "+rowCount+" rows affected"); }

Voorbeeld: DisplayAuthors We raadplegen de databank books We vragen de tabel authors op We tonen de gegevens in een JTextArea

De databank books Fig. 23.11 Table relationships in books. authors authorID firstName lastName authorISBN authorID isbn titles isbn title editionNumber copyright publisherID imageFile price 1 8 1 8 8 publishers publisherID publisherName 1 Fig. 23.11 Table relationships in books.

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 // 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.

Laad de klasse definitie voor de databank driver. 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. Laad de klasse definitie voor de databank driver. Roept de methode createStatement aan om een object te krijgen dat de interface Statement implementeert. Voert de query uit om alle gegevens uit de tabel authors op te halen getMetaData() haalt de metadata op van de ResultSet De methode getColumnCount levert het aantal kolommen van de ResultSet af

Voeg de namen van de kolommen toe aan StringBuffer results. 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 Voeg de namen van de kolommen toe aan StringBuffer results. Voeg de gegevens van elke rij uit de ResultSet toe aan de StringBuffer results. Creeer de GUI die de StringBuffer results toont, stel de grootte van het applicatie window en toon het applicatie window.

Sluit het Statement en de databank Connection. 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.

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

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 prepareStatement( query ) 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() methoden

Voorbeeld: PrepareStatement int filmNummer = 12; preparedStatement ps = con.prepareStatement( select * from films where filmnr = ? ); ps.setInt(1 , filmNummer ); rs = ps.executeQuery(); .... .... ps.setInt( 1 , 13 ); rs = ps.executeQuery(); Parameter 1 Parameter 1 Parameterindex

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 prepareCall( query ) 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

CallableStatement De query string bevat volgt de volgende syntax “{call <naam_van_procedure>([?[,?]])}” 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.

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()

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.

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.

Transactions, dirty read begin transaction update…. rollback Transaction 2 begin transaction select …. Data is nu foutief hhh Een dirty read treedt op wanneer data gelezen wordt tussen wijziging en een commit

Transactions, non-repeatable reads begin transaction select…. select…. Ander resultaat ! Transaction 2 begin transaction update …. commit hhh Een non-repeatable read treedt op wanneer twee dezelfde lees- opdrachten een verschillende waarde opleveren

Transactions, phantom reads begin transaction select….where update….where Ander resultaat ! Transaction 2 begin transaction update …. commit hhh hhh Een phantom read treedt op wanneer twee dezelfde leesopdrachten een verschillende dataset opleveren

Voorbeeld Gebruik van JTable en TableModel: De gebruiker kan een Query intypen en activeren. Het resultaat wordt getoond met behulp van een JTable.

import javax.swing.table.*; Javax.swing.AbstractTableModel voorziet een default implementatie voor de methoden van de interface TableModel import java.sql.*; import java.util.*; import javax.swing.table.*; // opgelet ResultSet rijen en kolommen worden vanaf 1 geindexeerd // opgelet JTable rijen en kolommen worden vanaf 0 geindexeerd public class ResultSetTableModel extends AbstractTableModel { private Connection connection; private Statement statement; private ResultSet resultSet; private ResultSetMetaData metaData; private int numberOfRows; private boolean connectedToDatabase = false;

public ResultSetTableModel( String driver, String url, String query ) throws SQLException, ClassNotFoundException { // maak verbinding en initialiseer resultSet, metaData en aantal rows (methode setQuery) Class.forName( driver ); connection = DriverManager.getConnection( url ); statement = connection.createStatement( ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY ); connectedToDatabase = true; setQuery( query ); }

// levert een Class object die het kolomtype voorstelt public Class getColumnClass( int column ) throws IllegalStateException { if ( !connectedToDatabase ) throw new IllegalStateException( "Not Connected to Database" ); try // bepaal Java class van de kolom { String className = metaData.getColumnClassName( column + 1 ); return Class.forName( className ); } catch ( Exception exception ) { exception.printStackTrace(); } // bij problemen, veronderstel type Object return Object.class;

// levert het aantal kolommen in de ResultSet public int getColumnCount() throws IllegalStateException { if ( !connectedToDatabase ) throw new IllegalStateException( "Not Connected to Database" ); try { return metaData.getColumnCount(); } catch ( SQLException sqlException ) { sqlException.printStackTrace(); } // bij problemen, veronderstel 0 kolommen return 0;

// levert de naam van een bepaalde kolom in de ResultSet public String getColumnName( int column ) throws IllegalStateException { if ( !connectedToDatabase ) throw new IllegalStateException( "Not Connected to Database" ); try { return metaData.getColumnName( column + 1 ); } catch ( SQLException sqlException ) { sqlException.printStackTrace(); } // bij problemen, veronderstel lege string als kolomnaam return "";

// levert het aantal rijen in de ResultSet public int getRowCount() throws IllegalStateException { if ( !connectedToDatabase ) throw new IllegalStateException( "Not Connected to Database" ); return numberOfRows; } // levert de waarde van een bepaalde cel (rij,kolom) uit de ResultSet public Object getValueAt( int row, int column ) throws IllegalStateException try { resultSet.absolute( row + 1 ); return resultSet.getObject( column + 1 ); catch ( SQLException sqlException ) { sqlException.printStackTrace(); } // bij problemen, veronderstel lege string als value return "";

// set nieuwe database query string en activeer public void setQuery( String query ) throws SQLException, IllegalStateException { if ( !connectedToDatabase ) throw new IllegalStateException( "Not Connected to Database" ); resultSet = statement.executeQuery( query ); metaData = resultSet.getMetaData(); resultSet.last(); // zet cursor op laatste rij numberOfRows = resultSet.getRow(); // get rij nummer fireTableStructureChanged(); // notify JTable dat het model is gewijzigd ! } public void disconnectFromDatabase() { try { statement.close(); connection.close(); catch ( SQLException sqlException ) { sqlException.printStackTrace(); } finally { connectedToDatabase = false;

import java.awt.*; import java.awt.event.*; import java.sql.*; import java.util.*; import javax.swing.*; import javax.swing.table.*; public class DisplayQueryResults extends JFrame { static final String JDBC_DRIVER = " sun.jdbc.odbc.JdbcOdbcDriver"; static final String DATABASE_URL = "jdbc:odbc:books"; static final String DEFAULT_QUERY = "SELECT * FROM authors"; private ResultSetTableModel tableModel; private JTextArea queryArea;

public DisplayQueryResults() { super( "Displaying Query Results" ); try // create ResultSetTableModel and display database table { Class.forName(JDBC_DRIVER); tableModel = new ResultSetTableModel( JDBC_DRIVER, DATABASE_URL, DEFAULT_QUERY ); queryArea = new JTextArea( DEFAULT_QUERY, 3, 100 ); queryArea.setWrapStyleWord( true ); queryArea.setLineWrap( true ); JScrollPane scrollPane = new JScrollPane( queryArea, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER ); JButton submitButton = new JButton( "Submit Query" ); Box box = Box.createHorizontalBox(); box.add( scrollPane ); box.add( submitButton ); JTable resultTable = new JTable( tableModel ); Container c = getContentPane(); c.add( box, BorderLayout.NORTH ); c.add( new JScrollPane( resultTable ), BorderLayout.CENTER );

submitButton.addActionListener( new ActionListener() { public void actionPerformed( ActionEvent event ) // geef de query door aan het table model { try { tableModel.setQuery( queryArea.getText() ); } catch ( SQLException e ) { JOptionPane.showMessageDialog( null, e.getMessage(),"Database error",JOptionPane.ERROR_MESSAGE ); // try to recover from invalid user query by executing default query try { tableModel.setQuery(DEFAULT_QUERY ); queryArea.setText(DEFAULT_QUERY ); } { JOptionPane.showMessageDialog(null,e.getMessage(),"Database error",JOptionPane.ERROR_MESSAGE); tableModel.disconnectFromDatabase(); System.exit( 1 ); } );

setSize( 500, 250 ); setVisible( true ); } catch ( ClassNotFoundException classNotFound ) { JOptionPane.showMessageDialog( null, "Cloudscape driver not found", "Driver not found", JOptionPane.ERROR_MESSAGE ); System.exit( 1 ); catch ( SQLException sqlException ) { JOptionPane.showMessageDialog( null, sqlException.getMessage(), "Database error", JOptionPane.ERROR_MESSAGE ); tableModel.disconnectFromDatabase(); System.exit( 1 ); setDefaultCloseOperation( DISPOSE_ON_CLOSE ); // default is HIDE_ON_CLOSE addWindowListener( new WindowAdapter() { public void windowClosed( WindowEvent event ) { tableModel.disconnectFromDatabase(); System.exit( 0 ); } ); public static void main( String args[] ) { new DisplayQueryResults();