chapter 101© copyright janson industries 2011 database access ▮ jdbc ▮ db access objects ▮...
TRANSCRIPT
chapter 10 1© copyright Janson Industries 2011
Database Access
▮ JDBC
▮ DB Access objects
▮ Encapsulation
▮ Abstract classes
▮ CRUD
chapter 10 2© copyright Janson Industries 2011
Database Access
▮ Need DBMS-specific software (called a driver) to access the various DBMSs
▮ Why? Java follows a DB access protocol called JDBC (Java DB Connectivity)
▮ None of the DBMSs directly support JDBC▮ However each DBMS vendor supplies a
driver
▮ The driver converts JDBC requests to the DBMS’s protocol
chapter 10 3© copyright Janson Industries 2011
Drivers
Drivers
DBMS Java Pgm
DB2OracleODBC
JDBC
chapter 10 4© copyright Janson Industries 2011
Drivers
▮ ODBC (Open DB Connectivity) is the MS Access DBMS’s protocol
▮ sun.jdbc.odbc.JdbcOdbcDriver, the driver class, is included in the JRE (and RAD)
▮ For DB2 and Oracle you must download the driver and include in classpath
▮ The headache with Access is you must define the DB as an ODBC data source
chapter 10 5© copyright Janson Industries 2011
Drivers
▮ For Access: DB must reside and be defined as an ODBC data source on the computer where the application will run
▮ To run in RAD or as an application this means on the client
▮ To run on a server, this means on the computer that is acting as the server
▮ An Access DB cannot be accessed remotely
chapter 10 6© copyright Janson Industries 2011
Drivers
▮ For other DBMS’s:
▮ Download the driver
▮ Set the class path to point to the driver
▮ To run in RAD: change the Java Build Path
▮ To run on a client or server: change that computer’s classpath environment variable to point to the driver
chapter 10 7© copyright Janson Industries 2011
Running on client
▮ For instance to access DB2 on a IBM Power System:
ADDENVVAR ENVVAR(CLASSPATH) VALUE('/QIBM/ProdData/Http/Public/jt400/lib/jt400.zip')
▮ On a Windows PC, change the set classpath to include jt400.zip
path=c:\jdk\binSet classpath=.;\jdk\lib\tools.jar;c:\jtopen\lib\jt400.jar
chapter 10 8© copyright Janson Industries 2011
Accessing a DB
▮ In a java pgm, 4 things, several steps:
▮ 1. Register/load the driver
▮ 2. Get a Connection object, using the DriverManager class
▮ 3. Create a Statement object, using the Connection object
▮ 4. Define and execute SQL statements, using the Statement object
chapter 10 9© copyright Janson Industries 2011
Accessing a DB
▮ The Class class (yikes!) allows you to register/load the driver
▮ A DriverManager allows you to get a Connection object
▮ A Connection allows you to create a Statement object
chapter 10 10© copyright Janson Industries 2011
Register/load the driver
▮ Instead of “instantiating an object of the driver”, load (register) the driver in the JVM with the “class loader”:
▮ Essentially returns a driver object (of the type specified) as a Class object and makes it available to the JVM
▮ Just like getInstance(), another way to create an object
Class.forName(“com.ibm.db2.jdbc.app.DB2Driver”)
chapter 10 11© copyright Janson Industries 2011
Connection Object
▮ A DBMS connection must be established (even if the Java application is running on the same machine as the DBMS)
▮ To create a Connection must specify the
▮ Driver to be used
▮ DB (possibly including a URL or IP address)
▮ Optionally, a user ID and PW
chapter 10 12© copyright Janson Industries 2011
DB Identifier
▮ Identified as: driver:subprotocol:subname
▮ Optional subprotocol ids a DB connectivity mechanism (supported by the driver)
▮ The subname ids the DB and its syntax depends on the protocol and subprotocol
▮ If specifying a network address as the subname, follow the standard naming convention of: //hostname:port/subsubname
▮ Subsubname has unique internal syntax
static String url = ("jdbc:db2:subprotocol:subname);
chapter 10 13© copyright Janson Industries 2011
DB URL
▮ For MS Access on Windows
▮ For Oracle
▮ For DB2 on an IBM Power System
static String url = ("jdbc:odbc:TNT Database”);
static String url = ("jdbc:as400:1.2.3.4”);
static String url=("jdbc:oracle:thin:@1.2.3.4:1521:SID”);
chapter 10 14© copyright Janson Industries 2011
Properties Object
▮ Properties hold information for the driver
▮ Each driver expects its own set of info
▮ Most drivers expect user ID and password (not MS Access)
▮ You can create a property object and then set the values
static Properties p = new Properties();
: : :
p.put("naming", "sql");
p.put("user", "rjanson");
p.put("password", “jeter");
File namingconvention
chapter 10 15© copyright Janson Industries 2011
▮ Create a Connection object with the DriverManager’s static getConnection method
▮ Pass the String url and Properties object
▮ DriverManager searches for a suitable driver from those that were loaded (e.g., those that were registered with the .forName method) based on the protocol
con = DriverManager.getConnection(url, p);
Get a Connection Object
chapter 10 16© copyright Janson Industries 2011
Statement Object
▮ Created with the Connection object’s createStatement method
▮ Primary methods to perform SQL instructions:▮ executeQuery – SQL Select command▮ executeUpdate – SQL Insert, Delete,
Updatestmt.executeUpdate("INSERT INTO TNTDB.CUSTOMER " +
"VALUES(1, 'Joe Customer', '1 Main St.', " +
"'Jacksonville, FL 32233')");
Statement stmt = con.createStatement();
chapter 10 17© copyright Janson Industries 2011
Java Changes
▮ Add the following:
to access SQL related objects such as:▮ ResultSet
▮ Statement
▮ Connection
▮ SQLException
import java.sql.*;
chapter 10 18© copyright Janson Industries 2011
Result Sets
▮ All data is returned by a SQL select statement as a ResultSet object
▮ A result set is comprised of a:
▮ Table that is comprised of▮ Rows/records▮ Columns/fields
▮ A pointer/cursor that is used to move between the rows
chapter 10 19© copyright Janson Industries 2011
Result Sets
▮ Have a variety of methods to retrieve field data
▮ getXXX(field identifier) - where XXX is the data type (Int, String, etc.)
▮ Field can be identified by the field name or the column number
▮ Column number more efficient
▮ Field name better for documentation
chapter 10 20© copyright Janson Industries 2011
Result Sets
▮ .next() increments pointer to next row/record▮ Initially pointer set before the first row, so
must .next() to “prime the read”▮ Returns a Boolean value indicating
whether there is a record or not
▮ .previous(), .last()
▮ .relative(#) moves pointer # number of rows
chapter 10 21© copyright Janson Industries 2011
Result Set & Choice Example
try {
stmt = conn.createStatement();
select = "SELECT School FROM Schools ORDER BY School";
rs = stmt.executeQuery(select);
while (rs.next()){
schoolsCB.addItem(rs.getString(1));
}
stmt.close();
}
catch (SQLException sqlex) {
sqlex.printStackTrace();
System.out.println("\nSQL exception on query\n"); }
Populates Choicewith school names
chapter 10 22© copyright Janson Industries 2011
Encapsulation
▮ Many terms used to describe:
▮ Transparency
▮ Information hiding
▮ Implementation ignorance
▮ Programmers have an “interface” to an object with no idea of how it works
chapter 10 23© copyright Janson Industries 2011
Encapsulation
▮ Someone knows how to drive:▮ Turn the key
▮ Step on gas pedal
▮ Steer
▮ Step on brake pedal
▮ The driver doesn’t have to know how the car works or any of its internal components
chapter 10 24© copyright Janson Industries 2011
Encapsulation
▮ Many methods and data are hidden from the user/application
▮ Changes to the class (variables and methods) do not affect users of the class
▮ Data accessible only through publicly defined methods
chapter 10 25© copyright Janson Industries 2011
Encapsulation
DATA
Getters
SettersRules
Constructors
chapter 10 26© copyright Janson Industries 2011
Encapsulation
▮ If programmers can’t directly access the data, their applications can’t screw it up!!
▮ PUBLIC methods comprise the interface
▮ PRIVATE methods for internal functions and non-user fields
chapter 10 27© copyright Janson Industries 2011
Encapsulate a File/Table
▮ Define a class for the file (ex. TransTable)
▮ In the class, define private variables for each field in the file
▮ For each private variable:▮ Define a getter method▮ Define a setter with validation functions
▮ Define CRUD functions▮ Define functions to return associated
objects (customer purchase orders)▮ Define business functions (getTotal)
chapter 10 28© copyright Janson Industries 2011
Business Change
▮ Selling to schools via purchase orders
▮ Have a DB called Sales with a table called TxTable
▮ Will create a new class to encapsulate TxTable called TransTable
▮ Need a new frame to add PO sales info
chapter 10 29© copyright Janson Industries 2011
PO Sale
▮ Create a new POSale Frame to input PO sale transaction info
Chapter 10 30© copyright Janson Industries 2011
In class assg
Sales DB
User
Sales Info TxTable
EmptyFrame
Creates
PO Sale Sales Info
Sales Info
TransTable
chapter 10 31© copyright Janson Industries 2011
This new class will eventually have all
these methods
chapter 10 32© copyright Janson Industries 2011
How to Encapsulate a File▮ TransTable class will encapsulate the
TxTable file (with these fields)▮ School – char 25▮ Customer – char 30▮ PurchDate – char 10▮ ItemName – char 30▮ Qty – long integer (4 bytes)▮ Price – currency▮ PayDate – char 10▮ PONum – char 15▮ Comments - memo▮ PaidAmt – currency
chapter 10 33© copyright Janson Industries 2011
34chapter 10 © copyright Janson Industries 2011
import java.util.*;
import java.util.Date;
import java.sql.*;
import java.text.DateFormat;
public class TransTable {
private String school;
private String customer;
private String purchDate;
private String itemName;
private int qty;
private double price;
private String payDate;
private String pONum;
private String comments;
private double paidAmt;
How to Encapsulate a File
▮ Define a private variable for each field
Need to import various date classes and the sql
package
chapter 10 35© copyright Janson Industries 2011
How to Encapsulate a File
Need date variables/objects
Need DBMSvariables/
objects
Create getters
chapter 10 36© copyright Janson Industries 2011
How to Encapsulate a File
public void setQty(int qty) {
this.qty = qty;}
public void setPrice(double price) {
this.price = price;}
public void setComments(String comments) {
this.comments = comments;}
public void setPaidAmt(double paidAmt) {
this.paidAmt = paidAmt;}
public void setPurchDate() {
this.purchDate = String.valueOf(dfShort.format(date));}
public void setPayDate() {
this.payDate = String.valueOf(dfShort.format(date));}
public void setSchool(String school) throws InvalidLengthException {
if (school.length() > 25)
throw new InvalidLengthException("School", school, 25);
this.school = school;}
Create setters (some with validation functions)
chapter 10 37© copyright Janson Industries 2011
How to Encapsulate a File
public void setCustomer(String customer) throws InvalidLengthException {
if (customer.length() > 30)
throw new InvalidLengthException("Customer", customer, 30);
this.customer = customer;
}
public void setPONum(String pONum) throws InvalidLengthException {
if (pONum.length() > 15)
throw new InvalidLengthException("PO Number", pONum, 15);
this.pONum = pONum;
}
public void setItemName(String itemName) throws InvalidLengthException {
if (itemName.length() > 30)
throw new InvalidLengthException("Item Name", itemName, 30);
this.itemName = itemName;}
}
Create and use a new Exception subclass
chapter 10 38© copyright Janson Industries 2011
InvalidLengthException class
public class InvalidLengthException extends Exception {
public InvalidLengthException(String field, String value, int length)
{ super("The value entered for " + field + ": " + value +
", is too big. \nMax length is " + length + ".");
} // end of constructor for InvalidLengthException
/** \n command line control */
public static void main(String args[]) {
System.out.println("Welcome to class invalidLengthException");
} // end main
} // end of class InvalidLengthException
chapter 10 39© copyright Janson Industries 2011
CRUD
▮ We need functions to Create, Read, Update and Delete transactions
▮ The create function is done with a simple default constructor (a constructor with no arguments)
▮ When invoked, this creates a TransTable object with all the private fields
public TransTable() {}
chapter 10 40© copyright Janson Industries 2011
CRUD
▮ Of course, a calling program will have to set all the values
▮ And a write function will have to be executed to make the transaction info persistent
▮ In addition, need connection variables in order to do any reads/writes
chapter 10 41© copyright Janson Industries 2011
Application Probs
▮ We are executing the same SQL statement many times
▮ Statement is translated into ML every time executed
▮ Very inefficient
▮ Solution: PreparedStatement
chapter 10 42© copyright Janson Industries 2011
Prepared Statement
▮ A predefined/translated SQL statement
▮ Before executing, supply data for the statement
▮ More efficient
▮ Already created the variable as follows :
static PreparedStatement psAddTT = null;
chapter 10 43© copyright Janson Industries 2011
Prepared Statement
▮ Need a prepared statement object
▮ Retrieved from the connection object
▮ Therefore need a connection object
▮ The ?’s “hold” the place for the data values
psAddTT = con.prepareStatement("INSERT INTO EXAMPLES." +
"CUSTMAST VALUES(?, ?, ?, ?)");
chapter 10 44© copyright Janson Industries 2011
private void init() {
if (conn == null) {
try {
Class.forName(driver);
p.put("naming", "sql");
p.put("user", "anonymous");
p.put("password", "guest");
conn = DriverManager.getConnection(url, p);
} catch (ClassNotFoundException e) {
System.out.println("couldn't find jdbc/odbc driver");
e.printStackTrace();
System.exit(1);
} catch (SQLException e) {
System.out.println("couldn't connect");
e.printStackTrace();
System.exit(1);
}
} }
init creates connection to DB
init
chapter 10 45© copyright Janson Industries 2011
...and creates the statement objects needed to access
data in the DB
init
chapter 10 46© copyright Janson Industries 2011
Access a DB
▮ Need to call init from all constructors
▮ Change null constructor to run init
▮ Time to test, add the following main method and run as Java app
public TransTable() {init();}
public static void main(String[] args) {
TransTable tt = new TransTable();
System.out.println("Created a TransTable object");
}
chapter 10 47© copyright Janson Industries 2011
Never defined the DB as an ODBC data source
chapter 10 48© copyright Janson Industries 2011
Click Start, Control Panel, Administrative Tools
Data Sources (ODBC)
Click Add
chapter 10 49© copyright Janson Industries 2011
Select Microsoft Access Driver and click Finish
chapter 10 50© copyright Janson Industries 2011
If Access Driver doesn’t appear and you are running 64 bit Win7, here are links on work
around:http://answers.microsoft.com/en-us/office/forum/office_2007-excel/no-odbc-drivers-
available-for-excel-or-access-in/001c234b-dfd5-4378-a325-c4f1482fb6fd
http://stackoverflow.com/questions/6721702/windows-7-64-bit-odbc-drivers-for-ms-access-missing
chapter 10 51© copyright Janson Industries 2011
Specify Sales and click Select
Locate and select the DB file then click OK
chapter 10 52© copyright Janson Industries 2011
Click OK
© copyright Janson Industries 2011chapter 10 53Click OK
Sales appears in Data Source list
chapter 10 54© copyright Janson Industries 2011
Test again
chapter 10 55© copyright Janson Industries 2011
PO Sale
▮ Encapsulating TransTable will make other classes (like POSale) that use the DB simpler
▮ Created a new PO Sale Frame to capture PO sale transaction info
chapter 10 56© copyright Janson Industries 2011
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;import java.awt.Dimension;import java.awt.Label;import java.awt.Rectangle;import java.awt.TextField;import java.awt.Button;import java.awt.Point;
public class POSale extends Frame implements ActionListener, WindowListener {
private static final long serialVersionUID = 1L;
private Button addBtn = null; private Label custNameLbl = null;
private TextField custNameTF = null; private Label itemNameLbl = null;
private TextField itemNameTF = null; private Label qtyLbl = null;
private TextField qtyTF = null; private Label priceLbl = null;
private TextField priceTF = null; private Label resultLbl = null;
private Label schoolLbl = null; private TextField schoolTF = null;
private Label commentLbl = null; private TextField commentsTF = null;
private TextField pONumTF = null; private Label pONumLbl = null;
POSale
Visual components
chapter 10 57© copyright Janson Industries 2011
public void windowActivated(WindowEvent e) {}
public void windowClosed(WindowEvent e) {}
public void windowClosing(WindowEvent e) {
this.dispose();}
public void windowDeactivated(WindowEvent e) {}
public void windowDeiconified(WindowEvent e) {}
public void windowIconified(WindowEvent e) {}
public void windowOpened(WindowEvent e) {}
private Button getAddBtn() { if (addBtn == null) {
addBtn = new Button();addBtn.setLabel("Add");addBtn.setLocation(new Point(237, 178));addBtn.setSize(new Dimension(60, 23));addBtn.addActionListener(this);
} return addBtn;}
private TextField getCustNameTF() {
if (custNameTF == null) {
custNameTF = new TextField();
custNameTF.setBounds(new Rectangle(147, 45, 140, 23));
}
return custNameTF;
}
Window Listenermethods
Visual component
getters
chapter 10 58© copyright Janson Industries 2011
private TextField getItemNameTF() { if (itemNameTF == null) {
itemNameTF = new TextField();
itemNameTF.setBounds(new Rectangle(147, 78, 140, 23));}
return itemNameTF; }
private TextField getQtyTF() { if (qtyTF == null) {
qtyTF = new TextField();
qtyTF.setBounds(new Rectangle(108, 111, 32, 23)); }
return qtyTF; }
private TextField getPriceTF() { if (priceTF == null) {
priceTF = new TextField();
priceTF.setBounds(new Rectangle(199, 111, 60, 23)); }
return priceTF;}
private TextField getSchoolTF() { if (schoolTF == null) {
schoolTF = new TextField();
schoolTF.setBounds(new Rectangle(389, 45, 113, 23)); }
return schoolTF;}
private TextField getCommentsTF() { if (commentsTF == null) {
commentsTF = new TextField();
commentsTF.setBounds(new Rectangle(389, 79, 113, 55));}
return commentsTF;}
private TextField getPONumTF() { if (pONumTF == null) {
pONumTF = new TextField();
pONumTF.setBounds(new Rectangle(331, 111, 47, 23)); }
return pONumTF;}
Remaining visual
componentgetters
chapter 10 59© copyright Janson Industries 2011
Salepublic POSale() {
super();
initialize();
}
private void initialize() {pONumLbl = new Label(); pONumLbl.setBounds(new Rectangle(265, 111, 62, 23));
pONumLbl.setText("PO Num:"); commentLbl = new Label();
commentLbl.setBounds(new Rectangle(307, 78, 71, 23)); commentLbl.setText("Comments:");
schoolLbl = new Label(); schoolLbl.setBounds(new Rectangle(325, 45, 53, 23));
schoolLbl.setText("School: "); resultLbl = new Label();
resultLbl.setBounds(new Rectangle(14, 145, 508, 23)); resultLbl.setAlignment(Label.CENTER);
resultLbl.setText(""); priceLbl = new Label();
priceLbl.setBounds(new Rectangle(147, 111, 45, 23)); priceLbl.setText("Price:");
qtyLbl = new Label(); qtyLbl.setBounds(new Rectangle(39, 111, 45, 23));
qtyLbl.setText("Quantity:"); itemNameLbl = new Label();
itemNameLbl.setBounds(new Rectangle(61, 78, 79, 23)); itemNameLbl.setText("Item Name:");
custNameLbl = new Label(); custNameLbl.setBounds(new Rectangle(31, 45, 109, 23));
custNameLbl.setText("Customer Name:");
this.setLayout(null); this.setSize(535, 214); this.setTitle("PO Sale");
this.setVisible(true); this.add(getAddBtn(), null); this.add(custNameLbl, null);
this.add(getCustNameTF(), null); this.add(itemNameLbl, null);
this.add(getItemNameTF(), null); this.add(qtyLbl, null);
this.add(getQtyTF(), null); this.add(priceLbl, null); this.add(getPriceTF(), null);
this.add(resultLbl, null); this.add(schoolLbl, null); this.add(getSchoolTF(), null);
this.add(commentLbl, null); this.add(getCommentsTF(), null);
this.add(getPONumTF(), null); this.add(pONumLbl, null); addWindowListener(this);
}
Null constructor that calls initialize
Defines labels, then frame
▮ And a main to test
▮ Speaking of test, code an actionPerformed to:▮ Create a TransTable object▮ Populate the object with info entered
in Frame▮ Clear the frame text fields▮ Display info from TransTable objectchapter 10 60© copyright Janson Industries 2011
Sale
public static void main(String[] args) {
new POSale();
}
chapter 10 61© copyright Janson Industries 2011
public void actionPerformed(ActionEvent e) {
TransTable newSale = new TransTable();
try {
newSale.setCustomer(custNameTF.getText());
newSale.setSchool(schoolTF.getText());
newSale.setPONum(pONumTF.getText());
newSale.setItemName(itemNameTF.getText());
newSale.setPrice(Double.valueOf(priceTF.getText()).doubleValue());
newSale.setComments(commentsTF.getText());
newSale.setQty(Integer.valueOf(qtyTF.getText()).intValue());
newSale.setPurchDate();
custNameTF.setText(""); schoolTF.setText("");
pONumTF.setText(""); priceTF.setText("");
commentsTF.setText(""); qtyTF.setText(""); itemNameTF.setText("");
System.out.println("Successfully created a TransTable object for PO Num:" + newSale.getPONum());
}
catch (InvalidLengthException err) {
System.out.println("\nLength exception: \n"+err.getMessage());
}
}
Creates newSale,
retrieves info from frame, sets
props
Proves object exists by displaying PO Num
Clears TFs
chapter 10 62© copyright Janson Industries 2011
Run POSale, enter a PO Num, click Add
chapter 10 63© copyright Janson Industries 2011
Success!
chapter 10 64© copyright Janson Industries 2011
PO Sale
▮ Might be nice if we put the info in the database table
▮ Need to finish CRUD functions in TransTable
▮ PO Sale will invoke the U of CRUD
chapter 10 65© copyright Janson Industries 2011
Prepared Statement
▮ In TransTable, before the insert can be performed, must supply values to the prepared statement:
psAddTT.setString(1, School);
psAddTT.setString(2, CustName);
psAddTT.setString(3, PurchDate);
: : :
psAddTT.executeUpdate();
chapter 10 66© copyright Janson Industries 2011
Prepared Statement
▮ Of course, the variables CustName, etc. had to be set to some values
▮ POSale does this after it creates the TransTable object (newSale)
newSale.setSchool(schoolTF.getText());
newSale.setCustName (custNameTF.getText());
newSale.setPurchDate();
: : : : :
chapter 10 67© copyright Janson Industries 2011
Update (in TransTable)
public void write() {
try {
psAddTT.setString(1, school);
psAddTT.setString(2, customer);
psAddTT.setString(3, purchDate);
psAddTT.setString(4, itemName);
psAddTT.setInt(5, qty);
psAddTT.setDouble(6, price);
psAddTT.setString(7, pONum);
psAddTT.setString(8, comments);
psAddTT.setDouble(9, 0);
psAddTT.executeUpdate(); }
catch (SQLException e) {
System.err.println("General SQL exception.");
System.err.println(e.getMessage()); }
}
Sets paid amount to zero
chapter 10 68© copyright Janson Industries 2011
POSale must invoke write in actionPerformed
Put out a user msg and comment out the test println
chapter 10 69© copyright Janson Industries 2011
PO Sale
▮ Notice that POSale doesn’t worry about connections.
▮ There are no:▮ Drivers▮ Driver managers▮ Connection objects▮ Prepared statements
▮ Encapsulating the file makes the client class’ logic/coding simpler!!
chapter 10 70© copyright Janson Industries 2011
Now when we run POSale, enter info, & click Add…
chapter 10 71© copyright Janson Industries 2011
…the info is inserted into the table
chapter 10 72© copyright Janson Industries 2011
Paying a PO
▮ Need the ability to mark a PO as paid
▮ New POPay frame will:
▮ Display a list of outstanding PO's with PO #, school, and date
▮ When user selects a PO, POPay (using the TransTable object) updates pay date and paid amt
Chapter 10 73© copyright Janson Industries 2011
Paying a PO
User
Framew/ POs
Creates
OutstandingPOs
TransTable
dummyTT
POPay
Sales DB
TransTable
PO’s where paidAmt = 0
chapter 10 74© copyright Janson Industries 2011
For each unpaid PO display PO#, School & PO Date
When you click on one...
chapter 10 75© copyright Janson Industries 2011
...the PayDate and PaidAmt are updated...
Chapter 10 76© copyright Janson Industries 2011
Paying a PO
Sales DB
User
SelectedPO
TransTable
Createsw/ selected PO #
realPO
Select PO info
Paid date& amount
POPay
Pay
TransTable
1
2
34
5
chapter 10 77© copyright Janson Industries 2011
read(String whereClause)
▮ There can be many read functions:▮ A read for a key value (a single record)▮ A read for all records in a table▮ A read for records based on a condition
▮ Therefore the actual read method needs to accept a where clause
▮ Other methods need to create the where clause and pass to read()
chapter 10 78© copyright Janson Industries 2011
read(String whereClause)
▮ Because the SQL read statement will be dynamically built can't use a prepared statement
▮ Must use a regular statement object
▮ That's why we created a variable
▮ And in init, created the statement object
private Statement stmt;
stmt = conn.createStatement();
chapter 10 79© copyright Janson Industries 2011
TransTable(String poNum)
▮ To retrieve a single record, create a constructor that accepts a key value
▮ Will build read to retrieve records based on a Where condition, so need a method to pass a null Where
▮ POPay only wants outstanding PO's ▮ Need a method to pass a where clause
that has the condition paid amount = 0
chapter 10 80© copyright Janson Industries 2011
read(String whereClause)
▮ The select statement simply returns a result set
▮ TransTable needs to: ▮ Assign the result set to a result set
variable▮ Retrieve data from the result set and set
the TransTable object properties
▮ read method will assign result set
▮ Will create a getDataFromRS method to get data and assign to properties
chapter 10 81© copyright Janson Industries 2011
Read
private ResultSet rs;
: : : :
private void read(String whereClause) {
try {
String select = "SELECT * FROM TxTable " +
whereClause;
rs = stmt.executeQuery(select);
rs.next();
} catch (SQLException sqlex) {
sqlex.printStackTrace();
System.out.println("\nSQL exception on Select\n");
}
}
read accepts a where clause if the where clause is blank, will retrieve all
records
"Priming read"
chapter 10 82© copyright Janson Industries 2011
Single Record Read
public TransTable(String ponum) {
this();
try {
this.read(" WHERE PONum = '" + ponum + "'");
this.getDataFromRS();
rs.close();
stmt.close();
} catch (SQLException e) {
System.out.println("SQL exceptions");
e.printStackTrace();
System.exit(1);
}
}
Builds where clause, executes read & getDataFromRS
Invokes the null constructor – why?
House cleaning, closes rs and statement
chapter 10 83© copyright Janson Industries 2011
getDataFromRS
private void getDataFromRS() {
try { school = rs.getString(1);
customer = rs.getString(2);
purchDate = rs.getString(3);
itemName = rs.getString(4);
qty = rs.getInt(5);
price = rs.getDouble(6);
payDate = rs.getString(7);
pONum = rs.getString(8);
comments = rs.getString(9);
paidAmt = rs.getDouble(10);
}
catch (SQLException sqlex) {
sqlex.printStackTrace();
System.out.println("\nSQL exception on rs get\n");
} }
chapter 10 84© copyright Janson Industries 2011
Other methods needed
▮ Still need:
▮ A delete function (not going to show/do)
▮ A getAll method
▮ Related business functions
▮ getOutStandingPOs method ▮ pass where clause of paidAmt = 0
▮ setPOPaid method
▮ Then must create POPay
▮ Passes a null where clause so all POs will be returned
▮ Pretty simple but notice it returns a result set
▮ This means the invoking object must handle the result set
chapter 10 85© copyright Janson Industries 2011
Get all POs
public ResultSet getAllPOs()
{
if (conn==null) { init();}
read("");
return rs;
}
▮ Again, pretty simple but it also returns a result set
▮ This means the invoking object (POPay) must handle the result set
chapter 10 86© copyright Janson Industries 2011
Outstanding POs
public ResultSet getOutStandingPOs()
{
if (conn==null) { init();}
read("WHERE PaidAmt = 0");
return rs;
}
▮ Will test with following main method
chapter 10 87© copyright Janson Industries 2011
Outstanding POs
public static void main(String[] args) {
TransTable tt = new TransTable();
ResultSet rsTest = tt.getOutStandingPOs();
try {
System.out.println("Got the first PO " + rsTest.getString(8));
} catch (SQLException sqlex) {
sqlex.printStackTrace();
System.out.println("SQL exception on rs get");
}
}
chapter 10 88© copyright Janson Industries 2011
▮ Need to update just the PayDate and PaidAmt fields
▮ Needed another statement variable
▮ In init, created & assigned statement object
▮ Then create two new methods:▮ One to build the SQL update statement▮ One to perform the update
chapter 10 89© copyright Janson Industries 2011
Updating (in TransTable)
private Statement updateStmt;
updateStmt = conn.createStatement();
chapter 10 90© copyright Janson Industries 2011
Updating (in TransTable)public void setPOPaid() {
this.setPayDate();
String totalCost = String.valueOf(qty * price);
String update = "Update TxTable Set PayDate = '" +
this.payDate + "', PaidAmt = " +
totalCost + “ WHERE PONum = '" +
this.pONum + "'";
this.update(update);
}
public void update(String sqlupdate) {
try {
updateStmt.executeUpdate(sqlupdate);
}
catch (SQLException e) {
System.err.println("General SQL exception.");
System.err.println(e.getMessage());
}
}
chapter 10 91© copyright Janson Industries 2011
POPay Frame
▮ Initially will display all outstanding POs
▮ User selects one
▮ POPay then:
▮ Creates a new TransTable object for the selected PO
▮ Invokes the setPOPaid method
chapter 10 92© copyright Janson Industries 2011
Assuming we have the data above
chapter 10 93© copyright Janson Industries 2011
For each unpaid PO display PO#, School & PO Date
When you click on one...
chapter 10 94© copyright Janson Industries 2011
...message displayed and list box cleared…
chapter 10 95© copyright Janson Industries 2011
...the PayDate and PaidAmt are updated
chapter 10 96© copyright Janson Industries 2011
Running again would show that the PO was updated
chapter 10 97© copyright Janson Industries 2011
import java.awt.Frame; import java.awt.event.ItemEvent;
import java.awt.event.ItemListener; import java.awt.event.WindowEvent;
import java.awt.event.WindowListener; import java.sql.ResultSet;
import java.sql.SQLException; import java.awt.List;
import java.awt.Rectangle; import java.awt.Label;
public class POPay extends Frame implements WindowListener, ItemListener {
private static final long serialVersionUID = 1L;
ResultSet rs;
private List outstandingPOLB = null;
private Label label = null;
public void windowActivated(WindowEvent e) {}
public void windowClosed(WindowEvent e) {}
public void windowClosing(WindowEvent e) {
this.dispose();
}
public void windowDeactivated(WindowEvent e) {}
public void windowDeiconified(WindowEvent e) {}
public void windowIconified(WindowEvent e) {}
public void windowOpened(WindowEvent e) {}
POPay Frame
2 visual comps (list & label) & a
result set
Window listener
methods
chapter 10 98© copyright Janson Industries 2011
public POPay() {
super();
TransTable dummyTT = new TransTable();
rs = dummyTT.getOutStandingPOs();
initialize();
}
POPay Constructor
Creates a TransTable object and retrieves
outstanding POs
chapter 10 99© copyright Janson Industries 2011
private void initialize() {
label = new Label();
label.setBounds(new Rectangle(5, 141, 291, 23));
label.setAlignment(Label.CENTER);
label.setText("Select the PO to be paid");
this.setLayout(null);
this.setSize(300, 200);
this.setTitle("Pay a PO");
this.setVisible(true);
this.add(getOutstandingPOLB(), null);
this.add(label, null);
addWindowListener(this);
}
Initialize (in POPay)
Defines label and frame and gets the
list
chapter 10 100© copyright Janson Industries 2011
▮ Need to add outstanding PO's to the list
▮ Tie an item listener to the list
List (in POPay)
chapter 10 101© copyright Janson Industries 2011
private List getOutstandingPOLB() {
if (outstandingPOLB == null) {
outstandingPOLB = new List();
outstandingPOLB.setBounds(new Rectangle(35, 66, 229, 64));
outstandingPOLB.addItemListener(this);
try {
do {
outstandingPOLB.add(rs.getString(8) +
" " + rs.getString(1) +
" " + rs.getString(3));
} while (rs.next());
} catch (SQLException e) {
e.printStackTrace();
}
}
return outstandingPOLB;
}
List (in POPay)
RAD generates code to create, size and position
Programmer adds listener & loop to retrieve PO info from result set &
add to list
chapter 10 102© copyright Janson Industries 2011
POPay
▮ This is a good time to test that:
▮ Connection works
▮ All outstanding POs are displayed
public static void main(String[] args) {
POPay pay = new POPay();
}
chapter 10 103© copyright Janson Industries 2011
Looking good!
chapter 10 104© copyright Janson Industries 2011
▮ itemStateChanged method must:
▮ Retrieve the selected item from LB
▮ Extract the PO # from the selected item
▮ Create a TransTable object for the PO #
▮ Invoke setPOPaid
▮ Clear the list
▮ Display the paid message
Item State Changed
chapter 10 105© copyright Janson Industries 2011
public void itemStateChanged (ItemEvent e) {
String selectedPO = outstandingPOLB.getSelectedItem();
int index = 0;
String pONum =
String.valueOf(selectedPO.charAt(index));
index++;
while(!(String.valueOf(selectedPO.charAt(index)).
equals(" "))) {
pONum = pONum +
String.valueOf(selectedPO.charAt(index));
index++;
}
TransTable realPO = new TransTable(pONum);
realPO.setPOPaid();
label.setText("PO# " + realPO.getPONum() + " paid");
outstandingPOLB.removeAll();
}
Retrieve PO info, get first char, assign to PO#
Loop through till a space is encountered – space means end of the
PO# reached
Point to next char
Create TransTable and invoke setPOPaid
Build and display message and clear POs from list
chapter 10 106© copyright Janson Industries 2011
Run and select PO # 82634
To verify:Check that PayDate and PaidAmt are updated
Run again and only 2 POs should be shown
chapter 10 107© copyright Janson Industries 2011
Enterprise Data
▮ Rarely use MS Access to store sizable amount of data
▮ Can consist of many DBs with many tables▮ Thousands of tables not unusual
▮ Tables stored and possibly moved between different types of DBMS:
▮
▮ DB2, Oracle, SQL Server, ...
chapter 10 108© copyright Janson Industries 2011
Enterprise Data
▮ Defining connection info and objects in each "encapsulating" (i.e. table/file) class redundant
▮ Takes up more space
▮ Longer to make changes
▮ Greater chance of error when making changes
▮ Inheritance can help!▮
chapter 10 109© copyright Janson Industries 2011
Inheritance
▮ By creating superclasses, we can reduce the amount of duplicate code
▮ For instance, all the connection variables and methods:▮ variables (url, password, driver, etc.)▮ conn ▮ init
▮ Define in one DBMS-type superclass and have table/file classes inherit them
chapter 10 110© copyright Janson Industries 2011
Abstract types
▮ A subclass (or implementing class) must have methods with the same signature as its superclass' abstract methods
▮ E.g. abstract methods are "behind" the WindowListener methods▮ All those methods you were forced to
code, are defined as abstract methods in the WindowListener class
▮ A class can also be defined as abstract▮ abstract classes cannot be instantiated
chapter 10 111© copyright Janson Industries 2011
Inheritance
▮ Remember the steps to encapsulate a file:▮ Define a class for the file
▮ Define private variables for each field in the file
▮ Define a getter and setter for each private variable
▮ Define CRUD functions
▮ Define functions to return associated objects (getOutStandingPOs())
▮ Define business functions (setPOPaid())
chapter 10 112© copyright Janson Industries 2011
Inheritance
▮ We can enforce consistency across all the encapsulating classes by creating “abstract” methods that define the encapsulation interface method’s signatures in a superclass
▮ I.e. define abstract CRUD methods in the superclass so that all subclasses must code CRUD methods the same way
chapter 10 113© copyright Janson Industries 2011
▮ DBFile class will define:▮ Common variables and functions▮ Abstract standard interface methods
▮ Individual DBMS classes define:▮ Unique values for that DBMS type
▮ Individual Table classes define:▮ Unique values for the table▮ Standard interface methods▮ Unique functions for that table
Multiple DBMS Example
chapter 10 114© copyright Janson Industries 2011
DBFileconn, url, driver, user, pw, etc.
private init();abstract delete(),write(), update(), read()
AccessFiledriver = ("sun.
jdbc.odbc.
JdbcOdbcDriver")
user =
pw =
DB2Filedriver = ("com.
ibm.as400.access
.AS400JDBCDriver")
user =
pw =
is a is a
OracleFiledriver= “oracle
.jdbc.driver.
OracleDriver”)
user =
pw =
Multiple DBMS Example
chapter 10 115© copyright Janson Industries 2011
Database Example
▮ We’ll create an abstract DBFile class to…
▮ Define connection variables// DBFile
import java.util.*;
import java.sql.*;
abstract class DBFile {
Connection conn = null;
String url = null;
String user, pw;
Properties p = new Properties();
String driver = null;
public boolean connExists = false;
Abstract classes
cannot be instantiated!!
chapter 10 116© copyright Janson Industries 2011
Database Example
▮ … and to…▮ Create a common connection method
initpublic void init() { if (conn == null) { try {
Class.forName(driver); p.put("naming", "sql");
p.put("user", user); p.put("password", pw);
conn = DriverManager.getConnection(url, p);
} catch (ClassNotFoundException e) {
System.out.println("couldn't find driver");
e.printStackTrace(); System.exit(1);
} catch (SQLException e) {
System.out.println("couldn't connect");
e.printStackTrace(); System.exit(1); } } }
chapter 10 117© copyright Janson Industries 2011
Database Example
▮ … and to:▮ Enforce CRUD
▮ Protected allow subclasses access▮ Even if in a different package
protected abstract void write();
protected abstract void update(String sqlStmt);
protected abstract void read(String whereClause);
protected abstract void delete(String sqlStmt);
protected abstract void getDataFromRS();
}
chapter 10 118© copyright Janson Industries 2011
Database Example
▮ You can have many different types of databases at many different locations▮ Local Access DB’s▮ Remote Oracle DB’s▮ Remote DB2 DB’s
▮ Need subclasses to define each “type” of DB’s (or multiple DBMS of same type on different machines) unique connection values▮ Driver, URL, PW, ID
chapter 10 119© copyright Janson Industries 2011
AccessFile Class
abstract class AccessFile extends DBFile {
public AccessFile () {
url = "jdbc:odbc:Sales";
driver = "sun.jdbc.odbc.JdbcOdbcDriver";
user = "anonymous";
pw = "guest";
}
}Also defined as abstract
classes
chapter 10 120© copyright Janson Industries 2011
DB2File Class
▮ Have to get the correct driver
▮ JTOpen available (on website) or free at:▮ http://sourceforge.net/projects/jt400/
files/JTOpen-full/7.3/jtopen_7_3.zip/download
// DB2File
abstract class DB2File extends DBFile {
public DB2File() {
url = "jdbc:as400://207.203.206.4/Sales";
driver = "com.ibm.as400.access.AS400JDBCDriver";
user = "bjanson";
pw = "jeter"; }
}
chapter 10 121© copyright Janson Industries 2011
Oracle File Class
▮ Have to get the correct driver
▮ OracleDriver on website or free at:▮ http://www.oracle.com/technology/
software/tech/java/sqlj_jdbc/index.html// Oracle File
abstract class OracleFile extends DBFile {
public OracleFile() {
url = "jdbc:oracle:thin:@207.203.206.4:1521:SID";
driver = "oracle.jdbc.driver.OracleDriver";
user = "bjanson";
pw = "jeter"; }
}
chapter 10 122© copyright Janson Industries 2011
DBFilepublic init();abstract delete, write, update, read
AccessFiledriver =
user =
pw =
TransTable
is a
Customer
is a is a
Database Example
chapter 10 123© copyright Janson Industries 2011
TransTable Changes
▮ TransTable is a subclass of AccessFile and AccessFile variables are inherited
▮ TransTable doesn’t define init() or variables (i.e. url) instead inherits from DBFile
import java.util.*;
: : :
public class TransTable extends AccessFile {
: : : :
//static Connection conn = null;
//static String url = ("jdbc:odbc:Sales");
//static Properties p = new Properties();
//static String driver = ("sun.jdbc.odbc.JdbcOdbcDriver");//private String userid = new String("student99");//private String pw = new String("pinrut");
chapter 10 124© copyright Janson Industries 2011
TransTable Changes
▮ Comment out old init
▮ Must still run init (inherited init) and create various statement objects
public TransTable() {
init();
try {
if (psAddTT == null) {
psAddTT = conn.prepareStatement("INSERT INTO "
+ "TxTable(School, Customer, PurchDate, ItemName, Qty,"
+ "Price, PONum, Comments, PaidAmt) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?)");
}
chapter 10 125© copyright Janson Industries 2011
TransTable Changes
if (stmt == null) {
stmt = conn.createStatement();
}
if (updateStmt == null) {
updateStmt = conn.createStatement();
}
} catch (SQLException e) {
System.out.println("couldn't connect");
e.printStackTrace();
System.exit(1);
}
}
protected void getDataFromRS() {...
protected void read(String whereClause) {...
chapter 10 126© copyright Janson Industries 2011
TransTable Class
▮ Have a small problem with TransTable: we never defined a delete method
▮ This is the error message when you don’t code a required abstract method:
▮ What should you do?
chapter 10 127© copyright Janson Industries 2011
Verify that POPay still works
chapter 10 128© copyright Janson Industries 2011
TransTable Class
DBFilepublic init();abstract delete, write, update, read
▮ If we moved TxTable from Access to DB2 on an IBM Power System…
▮ …just change TransTable to extend DB2File
DB2Fileurl=
driver =
user =
pw =
is a
TransTable
is a
chapter 10 129© copyright Janson Industries 2011
TransTable DB2 Class
// TransTable.java
import java.sql.*;
public class TransTable extends DB2File{
private Statement stmt;
public TransTable() {
init();....}
protected void delete(String whereClause) { }
No communication variables to
change
“Got around” abstract delete method
chapter 10 130© copyright Janson Industries 2011
TransTable Class
DBFilepublic init();abstract delete, write, update, read
▮ If we moved TxTable from DB2 on an IBM Power System to Oracle…
▮ …just change TransTable to extend OracleFile
OracleFileurl=
driver =
user =
pw =
is a
TransTable
is a
chapter 10 131© copyright Janson Industries 2011
TransTable DB2 Class
// TransTable.java
import java.sql.*;
public class TransTable extends OracleFile{
private Statement stmt;
public TransTable() {
init();....}
protected void delete(String whereClause) { }
No communication variables to
change
chapter 10 132© copyright Janson Industries 2011
TxTable DB2 Table
CREATE TABLE sales.txtable
(school char(25),
customer char(30),
purchdate char(10),
qty int,
itemname char(30),
price double,
paydate char(10),
ponum char(15),
comments char(100),
paidamt double)
Assuming the table was created
using this SQL
chapter 10 133© copyright Janson Industries 2011
TransTable Class
Do table classes or methods have any idea TxTable was moved?
chapter 10 134© copyright Janson Industries 2011
DB2 Table
▮ DB2 driver must be downloaded▮ jtopen folder on class website
▮ To run in RAD, driver must be added to Java Build Path
▮ Right click project and select properties
▮ Select Java Build Path
▮ Click Libraries tab
chapter 10 135© copyright Janson Industries 2011
Click Add External Jars...
chapter 10 136© copyright Janson Industries 2011
Drill down to the jtopen/lib folder and select jt400.jar
Click Open then OK
chapter 10 137© copyright Janson Industries 2011
jt400.jar added to project
chapter 10 138© copyright Janson Industries 2011
Run POSale, input a new PO
chapter 10 139© copyright Janson Industries 2011
chapter 10 140© copyright Janson Industries 2011
DB2 Table
chapter 10 141© copyright Janson Industries 2011
In Class Assg
▮ Create a class DispEmp that:
▮ Retrieves the contents of TNTDB.employee
▮ Displays the contents on a frame
chapter 10 142© copyright Janson Industries 2011
DB Problems
▮ If you get a Unhandled exceptions msg:
Unhandled exceptionType=Segmentation error vmState=0x00040000J9Generic_Signal_Number=00000004 ExceptionCode=c0000005 ExceptionAddress=738B72D7 ContextFlags=0001003fHandler1=7FEFA0C0 Handler2=7FECC180 InaccessibleAddress=00000000EDI=00000000 ESI=70B52000 EAX=00000000 EBX=00000000ECX=00000020 EDX=00000000EIP=738B72D7 ESP=6F77DDD4 EBP=6F77DDD8 EFLAGS=00010202GS=0000 FS=003B ES=0023 DS=0023Module=C:\Windows\WinSxS\x86_microsoft.vc80.crt_1fc8b3b9a1e18e3b_8.0.50727.4927_none_d08a205e442db5b5\MSVCR80.dllModule_base_address=738A0000 Offset_in_DLL=000172d7Target=2_40_20110401_055940 (Windows 7 6.1 build 7600)CPU=x86 (8 logical CPUs) (0xcf5d5000 RAM)----------- Stack Backtrace -----------_strnicmp+0x7c (0x738B72D7 [MSVCR80+0x172d7])_strnicmp+0xe9 (0x738B7344 [MSVCR80+0x17344])(0x713042BE [ACECORE+0x42be])---------------------------------------JVMDUMP006I Processing dump event "gpf", detail "" - please wait.JVMDUMP032I JVM requested System dump using 'K:\JavaBookWS\CE\core.20110331.160455.6620.0001.dmp' in response to an eventJVMDUMP010I System dump written to K:\JavaBookWS\CE\core.20110331.160455.6620.0001.dmpJVMDUMP032I JVM requested Snap dump using 'K:\JavaBookWS\CE\Snap.20110331.160455.6620.0002.trc' in response to an eventJVMDUMP010I Snap dump written to K:\JavaBookWS\CE\Snap.20110331.160455.6620.0002.trcJVMDUMP032I JVM requested Java dump using 'K:\JavaBookWS\CE\javacore.20110331.160455.6620.0003.txt' in response to an eventJVMDUMP010I Java dump written to K:\JavaBookWS\CE\javacore.20110331.160455.6620.0003.txtJVMDUMP013I Processed dump event "gpf", detail "".
chapter 10 143© copyright Janson Industries 2011
Dumps can be accessed from within RAD
chapter 10 144© copyright Janson Industries 2011
DB Problems
▮ Open the “dump” text file and scroll down to find the stack trace
chapter 10 145© copyright Janson Industries 2011
Access Assg
▮ On the class web site is an Access DB called TNTDB that you can download
▮ TNTDB has 2 tables
▮ employee (with employee 111)
▮ shipment
chapter 10 146© copyright Janson Industries 2011
chapter 10 147© copyright Janson Industries 2011
The tables are defined as follows:
chapter 10 148© copyright Janson Industries 2011
chapter 10 149© copyright Janson Industries 2011
Access Assg
▮ You’ll need to:▮ Download the DB▮ Define the DB as an ODBC data
source
▮ Define the ▮ driver as
sun.jdbc.odbc.JdbcOdbcDriver▮ URL as jdbc:odbc:TNT Database▮ userid as anonymous▮ password as guest
chapter 10 150© copyright Janson Industries 2011
DB2 Assg
▮ At PLEIONE.SEALINC.ORG is a DB2 database/schema on an IBM Power System called TNTDB
▮ TNTDB has 2 tables▮ Employee (has emps 111, 222, 333)▮ Shipment (has 7, 111, 8888)
▮ Your UserID is student99, and PW is pinrut ▮ Don’t forget about the driver!!
chapter 10 151© copyright Janson Industries 2011Shipment defined as above
chapter 10 152© copyright Janson Industries 2011
Oracle Assg
▮ Can only be accessed from on-campus!▮ Must use driver ojdbc14.zip on class
website
▮ Define URL as:jdbc:oracle:thin:@stora:1521:sora10
▮ In SQL, don’t reference TNTDB▮ Employee (has one emp, 999)▮ Shipment (has one shipment, 999)
▮ Your UserID is Scott, and PW is TIGER