JDBC - TI Aalst

advertisement
JDBC
Java DataBase Connectivity
1
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
2
JDBC implementatie
3
Driver types
4
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.
5
Basisstappen:
De 4 basisstappen:
 Registeren van een databasedriver
 Connectie met een databank maken
 Creatie van een Statement object
 Uitvoeren van een query, een update, …
6
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");
7
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);
8
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 subprotocol is odbc.
 De sub-naam verwijst naar de ODBC-DSN.
De sub-naam film is een lokale ODBC-DSN.
9
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”
10
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
11
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!
12
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”);
}
}
}
13
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
14
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
15
Het Statement object

De belangrijkste methoden zijn


executeQuery()
executeUpdate()
16
Het Statement object
ResultSet executeQuery( String SQL-query)
throws SQLException
Alleen select statements !
returnt een ResultSet object
17
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
18
Het Statement object
ResultSetMetaData getMetaData()
 throws SQLException
19
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();
}
20
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
21
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.
22
Voorbeeld: ResultSet
while ( rs.next() )
{
System.out.println(rs.getString(1)+
” “+rs.getString(2));
}
Op deze wijze kunnen we door alle records lopen
23
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.
24
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>");
for(int i=1;i<=colCount;i++)
resultaat.append("<td>"+rs.getString(i)+"</td>");
resultaat.append("</tr>");
voor gebruik binnen HTML
}
worden al de hier gebruikte
resultaat.append("</TABLE>\n</BODY>\n</HTML>\n");
types ingelezen als String
sqlViewPane.setText(resultaat.toString());
JEditorPane
contentType = text/html
25
Lezen uit de ResultSet
26
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();
27
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");
break;
default :
JOptionPane.showMessageDialog(this,"There are "+rowCount+" rows affected");
break;
}
28
Voorbeeld: DisplayAuthors



We raadplegen de databank books
We vragen de tabel authors op
We tonen de gegevens in een JTextArea
29
De databank books
authors
authorISBN
titles
1
8
1
authorID
firstName
isbn
isbn
8
authorID
title
editionNumber
lastName
copyright
8
publishers
publisherID
1
publisherID
imageFile
publisherName
price
Fig. 23.11 Table relationships in books.
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// Fig. 23.26: DisplayAuthors.java
// Displaying the contents of the authors table.
import
import
import
import
java.awt.*;
java.sql.*;
java.util.*;
javax.swing.*;
Importeer de package
java.sql, die klassen en
interfaces bevat voor de JDBC
API.
public class DisplayAuthors extends JFrame {
// JDBC driver name and database URL
static final String JDBC_DRIVER = "sun.jdbc.odbc.JdbcOdbcDriver";
static final String DATABASE_URL = "jdbc:odbc:books";
// declare Connection and Statement for accessing
// and querying database
private Connection connection;
private Statement statement;
// constructor connects to database, queries database, processes
// results and displays results in window
public DisplayAuthors()
{
super( "Authors Table of Books Database" );
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
try {
// connect to database books and query database
// load database driver class
Class.forName( JDBC_DRIVER );
Laad de klasse
definitie voor de
databank driver.
// establish connection to database
connection = DriverManager.getConnection( DATABASE_URL,””,””);
// create Statement for querying database
statement = connection.createStatement();
Roept de methode createStatement aan om een object te
// query database
krijgen dat de interface Statement implementeert.
ResultSet resultSet =
statement.executeQuery( "SELECT * FROM authors" );
Voert de query uit om alle gegevens uit de tabel authors op te halen
// process query results
StringBuffer results = new StringBuffer();
ResultSetMetaData metaData = resultSet.getMetaData();
int numberOfColumns = metaData.getColumnCount();
getMetaData() haalt de
metadata op van de
ResultSet
De methode getColumnCount
levert het aantal
kolommen van de ResultSet
af
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
for ( int i = 1; i <= numberOfColumns; i++ )
results.append( metaData.getColumnName( i ) + "\t" );
Voeg de namen van de
kolommen toe aan
StringBuffer
results.
results.append( "\n" );
while ( resultSet.next() ) {
for ( int i = 1; i <= numberOfColumns; i++ )
results.append( resultSet.getObject( i ) + "\t" );
results.append( "\n" );
}
Voeg de gegevens van elke rij uit de
ResultSet toe aan de StringBuffer
results.
// set up GUI and display window
JTextArea textArea = new JTextArea( results.toString() );
Container container = getContentPane();
container.add( new JScrollPane( textArea ) );
setSize( 300, 100 );
setVisible( true );
}
// end try
// set window size
// display window
Creeer de GUI die de
StringBuffer results
toont, stel de grootte van het
applicatie window en toon het
applicatie window.
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
// detect problems interacting with the database
catch ( SQLException sqlException ) {
JOptionPane.showMessageDialog( null, sqlException.getMessage(),
"Database Error", JOptionPane.ERROR_MESSAGE );
System.exit( 1 );
}
// detect problems loading database driver
catch ( ClassNotFoundException classNotFound ) {
JOptionPane.showMessageDialog( null, classNotFound.getMessage(),
"Driver Not Found", JOptionPane.ERROR_MESSAGE );
System.exit( 1 );
}
// ensure statement and connection are closed properly
finally {
try {
statement.close();
connection.close();
}
Sluit het Statement en de
databank Connection.
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
// handle exceptions closing statement and connection
catch ( SQLException sqlException ) {
JOptionPane.showMessageDialog( null,
sqlException.getMessage(), "Database Error",
JOptionPane.ERROR_MESSAGE );
System.exit( 1 );
}
}
}
// end DisplayAuthors constructor
// launch the application
public static void main( String args[] )
{
DisplayAuthors window = new DisplayAuthors();
window.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
}
}
// 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
36
Voorbeeld: PrepareStatement
int filmNummer = 12;
preparedStatement ps = con.prepareStatement( select * from films where filmnr = ? );
ps.setInt(1 , filmNummer );
Parameter 1
Parameter 1
Parameterindex
rs = ps.executeQuery();
....
....
ps.setInt( 1 , 13 );
rs = ps.executeQuery();
37
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
38
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.
39
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()
40
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.
41
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
42
opleveren.
Transactions, dirty read


Transaction1
begin
transaction
update….
Transaction 2

hhh


rollback
begin
transaction
select ….
Data is nu
foutief
Een dirty read treedt op wanneer data gelezen wordt tussen
wijziging en een commit
43
Transactions, non-repeatable reads


Transaction1
begin
transaction
select….
Transaction 2

hhh


select….
Ander resultaat !

begin
transaction
update ….
commit
Een non-repeatable read treedt op wanneer twee dezelfde leesopdrachten een verschillende waarde opleveren
44
Transactions, phantom reads


Transaction1
begin transaction
select….where
Transaction 2

hhh
hhh

update….where
Ander resultaat !


begin
transaction
update ….
commit
Een phantom read treedt op wanneer twee dezelfde leesopdrachten
een verschillende dataset opleveren
45
Voorbeeld

Gebruik van JTable en TableModel:


De gebruiker kan een Query intypen en
activeren.
Het resultaat wordt getoond met behulp
van een JTable.
46
47
import java.sql.*;
import java.util.*;
import javax.swing.table.*;
Javax.swing.Abstract
TableModel
voorziet een
default
implementatie
voor de methoden
van de interface
TableModel
// 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;
48
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 );
}
49
// 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;
}
50
// 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;
}
51
// 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 "";
}
52
// 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
{ if ( !connectedToDatabase )
throw new IllegalStateException( "Not Connected to Database" );
try
{ resultSet.absolute( row + 1 );
return resultSet.getObject( column + 1 );
}
catch ( SQLException sqlException ) { sqlException.printStackTrace(); }
// bij problemen, veronderstel lege string als value
return "";
}
53
// 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;
}
}
}
54
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;
55
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();
56
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 ); }
catch ( SQLException e )
{ JOptionPane.showMessageDialog(null,e.getMessage(),"Database error",JOptionPane.ERROR_MESSAGE);
tableModel.disconnectFromDatabase(); System.exit( 1 );
}
}
}
}
);
57
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();
}
}
58
Download