De presentatie wordt gedownload. Even geduld aub

De presentatie wordt gedownload. Even geduld aub

Java DataBase Connectivity

Verwante presentaties


Presentatie over: "Java DataBase Connectivity"— Transcript van de presentatie:

1 Java DataBase Connectivity
JDBC Java DataBase Connectivity

2 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

3 JDBC implementatie

4 Driver types

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

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

7 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");

8 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);

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

10 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”

11 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

12 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!

13 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”);

14 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

15 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

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

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

18 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

19 Het Statement object ResultSetMetaData getMetaData()
throws SQLException

20 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(); }

21 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

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

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

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

25 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

26 Lezen uit de ResultSet

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

28 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"); }

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

30 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 Table relationships in books.

31 1 // Fig. 23.26: DisplayAuthors.java
// Displaying the contents of the authors table. 3 import java.awt.*; import java.sql.*; import java.util.*; import javax.swing.*; 8 public class DisplayAuthors extends JFrame { 10 // JDBC driver name and database URL static final String JDBC_DRIVER = "sun.jdbc.odbc.JdbcOdbcDriver"; static final String DATABASE_URL = "jdbc:odbc:books"; 14 // declare Connection and Statement for accessing // and querying database private Connection connection; private Statement statement; 19 // constructor connects to database, queries database, processes // results and displays results in window public DisplayAuthors() { super( "Authors Table of Books Database" ); 25 Importeer de package java.sql, die klassen en interfaces bevat voor de JDBC API.

32 Laad de klasse definitie voor de databank driver.
26 try { 28 // connect to database books and query database 30 31 // load database driver class Class.forName( JDBC_DRIVER ); 34 // establish connection to database connection = DriverManager.getConnection( DATABASE_URL,””,””); 37 // create Statement for querying database statement = connection.createStatement(); 40 // query database ResultSet resultSet = statement.executeQuery( "SELECT * FROM authors" ); 44 // process query results StringBuffer results = new StringBuffer(); ResultSetMetaData metaData = resultSet.getMetaData(); 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

33 Voeg de namen van de kolommen toe aan StringBuffer results.
for ( int i = 1; i <= numberOfColumns; i++ ) results.append( metaData.getColumnName( i ) + "\t" ); 52 results.append( "\n" ); 54 while ( resultSet.next() ) { 56 for ( int i = 1; i <= numberOfColumns; i++ ) results.append( resultSet.getObject( i ) + "\t" ); 59 results.append( "\n" ); } 62 // set up GUI and display window JTextArea textArea = new JTextArea( results.toString() ); Container container = getContentPane(); 66 container.add( new JScrollPane( textArea ) ); 68 setSize( 300, 100 ); // set window size setVisible( true ); // display window 71 } // 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.

34 Sluit het Statement en de databank Connection.
// detect problems interacting with the database catch ( SQLException sqlException ) { JOptionPane.showMessageDialog( null, sqlException.getMessage(), "Database Error", JOptionPane.ERROR_MESSAGE ); 78 System.exit( 1 ); } 81 // detect problems loading database driver catch ( ClassNotFoundException classNotFound ) { JOptionPane.showMessageDialog( null, classNotFound.getMessage(), "Driver Not Found", JOptionPane.ERROR_MESSAGE ); 86 System.exit( 1 ); } 89 // ensure statement and connection are closed properly finally { 92 try { statement.close(); connection.close(); } 97 Sluit het Statement en de databank Connection.

35 98 // handle exceptions closing statement and connection
catch ( SQLException sqlException ) { JOptionPane.showMessageDialog( null, sqlException.getMessage(), "Database Error", JOptionPane.ERROR_MESSAGE ); 103 System.exit( 1 ); } } 107 } // end DisplayAuthors constructor 109 // launch the application public static void main( String args[] ) { DisplayAuthors window = new DisplayAuthors(); window.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); } 116 117 } // end class DisplayAuthors

36 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

37 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

38 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

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

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

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

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

43 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

44 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

45 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

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

47

48 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;

49 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 ); }

50 // 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;

51 // 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;

52 // 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 "";

53 // 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 "";

54 // 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;

55 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;

56 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 );

57 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 ); } );

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


Download ppt "Java DataBase Connectivity"

Verwante presentaties


Ads door Google