Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Database Access ▮ JDBC ▮ DB Access objects ▮ Encapsulation ▮ Abstract classes ▮ CRUD chapter 10 © copyright Janson Industries 2011 1 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 © copyright Janson Industries 2011 2 Drivers DBMS Drivers DB2 Oracle ODBC chapter 10 Java Pgm JDBC © copyright Janson Industries 2011 3 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 © copyright Janson Industries 2011 4 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 © copyright Janson Industries 2011 5 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 © copyright Janson Industries 2011 6 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\bin Set classpath=.;\jdk\lib\tools.jar;c:\jtopen\lib\jt400.jar chapter 10 © copyright Janson Industries 2011 7 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 © copyright Janson Industries 2011 8 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 © copyright Janson Industries 2011 9 Register/load the driver ▮ Instead of “instantiating an object of the driver”, load (register) the driver in the JVM with the “class loader”: Class.forName(“com.ibm.db2.jdbc.app.DB2Driver”) ▮ 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 chapter 10 © copyright Janson Industries 2011 10 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 © copyright Janson Industries 2011 11 DB Identifier ▮ Identified as: driver:subprotocol:subname static String url = ("jdbc:db2: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 chapter 10 © copyright Janson Industries 2011 12 DB URL ▮ For MS Access on Windows static String url = ("jdbc:odbc:TNT Database”); ▮ For Oracle static String url=("jdbc:oracle:thin:@1.2.3.4:1521:SID”); ▮ For DB2 on an IBM Power System static String url = ("jdbc:as400:1.2.3.4”); chapter 10 © copyright Janson Industries 2011 13 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 chapter 10 static Properties p = new Properties(); : : : File naming p.put("naming", "sql"); p.put("user", "rjanson"); convention p.put("password", “jeter"); © copyright Janson Industries 2011 14 Get a Connection Object ▮ Create a Connection object with the DriverManager’s static getConnection method ▮ Pass the String url and Properties object con = DriverManager.getConnection(url, p); ▮ 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 chapter 10 © copyright Janson Industries 2011 15 Statement Object ▮ Created with the Connection object’s createStatement method Statement stmt = con.createStatement(); ▮ Primary methods to perform SQL instructions: ▮ executeQuery – SQL Select command ▮ executeUpdate – SQL Insert, Delete, Update stmt.executeUpdate("INSERT INTO TNTDB.CUSTOMER " + "VALUES(1, 'Joe Customer', '1 Main St.', " + "'Jacksonville, FL 32233')"); chapter 10 © copyright Janson Industries 2011 16 Java Changes ▮ Add the following: import java.sql.*; to access SQL related objects such as: ▮ ResultSet ▮ Statement ▮ Connection ▮ SQLException chapter 10 © copyright Janson Industries 2011 17 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 © copyright Janson Industries 2011 18 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 © copyright Janson Industries 2011 19 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 © copyright Janson Industries 2011 20 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)); } Populates Choice stmt.close(); } with school names catch (SQLException sqlex) { sqlex.printStackTrace(); System.out.println("\nSQL exception on query\n"); } chapter 10 © copyright Janson Industries 2011 21 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 © copyright Janson Industries 2011 22 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 © copyright Janson Industries 2011 23 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 © copyright Janson Industries 2011 24 Encapsulation Getters Constructors DATA Rules chapter 10 Setters © copyright Janson Industries 2011 25 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 © copyright Janson Industries 2011 26 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 © copyright Janson Industries 2011 27 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 © copyright Janson Industries 2011 28 PO Sale ▮ Create a new POSale Frame to input PO sale transaction info chapter 10 © copyright Janson Industries 2011 29 In class assg Creates PO Sale Sales Info TransTable Sales Info Empty Frame Sales DB Sales Info TxTable User Chapter 10 © copyright Janson Industries 2011 30 This new class will eventually have all these methods chapter 10 © copyright Janson Industries 2011 31 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 chapter 10 © copyright Janson Industries 2011 ▮ PaidAmt – currency 32 chapter 10 © copyright Janson Industries 2011 33 How to Encapsulate a File ▮ Define a private variable for each field import import import import java.util.*; java.util.Date; java.sql.*; java.text.DateFormat; Need to import various date classes and the sql package 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; chapterprivate 10 © copyright Janson Industries 2011 double paidAmt; 34 How to Encapsulate a File private Date date = new Date(); private String currentDate; DateFormat dfShort = DateFormat.getDateInstance(DateFormat.SHORT); static Connection conn = null; static String url = ("jdbc:odbc:Sales"); static Properties p = new Properties(); static String driver = ("sun.jdbc.odbc.JdbcOdbcDriver"); static PreparedStatement psAddTT = null; static Statement stmt, updateStmt; public String getSchool() {return school;} public String getCustomer() {return customer;} public String getPurchDate() {return purchDate;} public String getItemName() {return itemName;} public int getQty() {return qty;} public double getPrice() {return price;} public String getPayDate() {return payDate;} public String getPONum() {return pONum;} public String getComments() {return comments;} chapter 10 copyright Janson Industries 2011 public double getPaidAmt()© {return paidAmt;} Need date variables/objects Need DBMS variables/objects Create getters 35 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));} Create setters (some with validation functions) public void setSchool(String school) throws InvalidLengthException { if (school.length() > 25) throw new InvalidLengthException("School", school, 25); chapter 10 © copyright Janson Industries 2011 36 this.school = school;} 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;} } chapter 10 © copyright Janson Industries 2011 Create and use a new Exception subclass 37 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 © copyright Janson Industries 2011 38 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) public TransTable() {} ▮ When invoked, this creates a TransTable object with all the private fields chapter 10 © copyright Janson Industries 2011 39 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 © copyright Janson Industries 2011 40 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 © copyright Janson Industries 2011 41 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 © copyright Janson Industries 2011 42 Prepared Statement ▮ Need a prepared statement object ▮ Retrieved from the connection object psAddTT = con.prepareStatement("INSERT INTO EXAMPLES." + "CUSTMAST VALUES(?, ?, ?, ?)"); ▮ Therefore need a connection object ▮ The ?’s “hold” the place for the data values chapter 10 © copyright Janson Industries 2011 43 init 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); } } chapter } 10 © copyright Janson Industries 2011 init creates connection to DB 44 init try { if (psAddTT == null) { psAddTT = conn.prepareStatement("INSERT INTO " + "TxTable(School, Customer, PurchDate, ItemName, Qty," + "Price, PONum, Comments, PaidAmt) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?)"); } 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); } } chapter 10 © copyright Janson Industries 2011 45 ...and creates the statement objects needed to access data in the DB Access a DB ▮ Need to call init from all constructors ▮ Change null constructor to run init public TransTable() {init();} ▮ Time to test, add the following main method and run as Java app public static void main(String[] args) { TransTable tt = new TransTable(); System.out.println("Created a TransTable object"); } chapter 10 © copyright Janson Industries 2011 46 Never defined the DB as an ODBC data source chapter 10 © copyright Janson Industries 2011 47 Click Start, Control Panel, Administrative Tools Data Sources (ODBC) Click Add chapter 10 © copyright Janson Industries 2011 48 Select Microsoft Access Driver and click Finish chapter 10 © copyright Janson Industries 2011 49 If Access Driver doesn’t appear and you are running 64 bit Win7, here are links on work around: http://answers.microsoft.com/enus/office/forum/office_2007-excel/no-odbc-driversavailable-for-excel-or-access-in/001c234b-dfd5-4378a325-c4f1482fb6fd http://stackoverflow.com/questions/6721702/windo ws-7-64-bit-odbc-drivers-for-ms-access-missing chapter 10 © copyright Janson Industries 2011 50 Specify Sales and click Select Locate and select the DB file then click OK chapter 10 © copyright Janson Industries 2011 51 Click OK chapter 10 © copyright Janson Industries 2011 52 Sales appears in Data Source list chapter 10 © copyright Janson Industries 2011 Click OK 53 Test again chapter 10 © copyright Janson Industries 2011 54 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 © copyright Janson Industries 2011 55 import import import import import import import import import import import java.awt.Frame; java.awt.event.ActionEvent; java.awt.event.ActionListener; java.awt.event.WindowEvent; java.awt.event.WindowListener; java.awt.Dimension; java.awt.Label; java.awt.Rectangle; java.awt.TextField; java.awt.Button; java.awt.Point; POSale public class POSale extends Frame implements ActionListener, WindowListener { private private private private private private private private private static final long serialVersionUID = Button addBtn = null; private TextField custNameTF = null; private TextField itemNameTF = null; private TextField qtyTF = null; private TextField priceTF = null; private Label schoolLbl = null; private Label commentLbl = null; private TextField pONumTF = null; private chapter 10 1L; Label custNameLbl = null; Label itemNameLbl = null; Label qtyLbl = null; Label priceLbl = null; Label resultLbl = null; TextField schoolTF = null; TextField commentsTF = null; Label pONumLbl = null; Visual components © copyright Janson Industries 2011 56 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) {} Window Listener methods 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; } Visual component getters private TextField getCustNameTF() { if (custNameTF == null) { custNameTF = new TextField(); custNameTF.setBounds(new Rectangle(147, 45, 140, 23)); } return custNameTF; chapter 10 © copyright Janson Industries 2011 } 57 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;} Remaining visual component getters 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;} chapter 10 © copyright Janson Industries 2011 58 public POSale() { super(); initialize(); } Null constructor that calls initialize Sale private void initialize() { Defines labels, then frame 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); chapter 10 © copyright Janson Industries 2011 59 } Sale ▮ And a main to test public static void main(String[] args) { new POSale(); } ▮ 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 object chapter 10 © copyright Janson Industries 2011 60 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()); } Creates newSale, retrieves info from frame, sets props Clears TFs catch (InvalidLengthException err) { System.out.println("\nLength exception: \n"+err.getMessage()); } } Proves object exists by displaying PO Num chapter 10 © copyright Janson Industries 2011 61 Run POSale, enter a PO Num, click Add chapter 10 © copyright Janson Industries 2011 62 Success! chapter 10 © copyright Janson Industries 2011 63 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 © copyright Janson Industries 2011 64 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 © copyright Janson Industries 2011 65 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 © copyright Janson Industries 2011 66 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(); } Sets paid amount to zero catch (SQLException e) { System.err.println("General SQL exception."); System.err.println(e.getMessage()); } chapter}10 © copyright Janson Industries 2011 67 POSale must invoke write in actionPerformed Put out a user msg and comment out the test println chapter 10 © copyright Janson Industries 2011 68 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 © copyright Janson Industries 2011 69 Now when we run POSale, enter info, & click Add… chapter 10 © copyright Janson Industries 2011 70 …the info is inserted into the table chapter 10 © copyright Janson Industries 2011 71 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 © copyright Janson Industries 2011 72 Paying a PO dummyTT Creates TransTable POPay Outstanding POs Frame w/ POs PO’s where paidAmt = 0 Sales DB User Chapter 10 TransTable © copyright Janson Industries 2011 73 For each unpaid PO display PO#, School & PO Date When you click on one... chapter 10 © copyright Janson Industries 2011 74 ...the PayDate and PaidAmt are updated... chapter 10 © copyright Janson Industries 2011 75 Paying a PO 2 Creates w/ selected PO # POPay realPO Pay 4 Selected PO User Chapter 10 1 3 TransTable Select PO info Paid date & amount Sales DB TransTable 5 © copyright Janson Industries 2011 76 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 © copyright Janson Industries 2011 77 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 private Statement stmt; ▮ And in init, created the statement object stmt = conn.createStatement(); chapter 10 © copyright Janson Industries 2011 78 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 © copyright Janson Industries 2011 79 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 © copyright Janson Industries 2011 80 Read read accepts a where clause if the where clause is blank, will retrieve all records 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"); } © copyright Janson Industries 2011 }chapter 10 "Priming read" 81 Single Record Read Invokes the null constructor – why? 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 House cleaning, closes rs and statement chapter 10 © copyright Janson Industries 2011 82 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 © copyright Janson Industries 2011 83 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 chapter 10 © copyright Janson Industries 2011 84 Get all POs ▮ Passes a null where clause so all POs will be returned ▮ Pretty simple but notice it returns a result set public ResultSet getAllPOs() { if (conn==null) { init();} read(""); return rs; } ▮ This means the invoking object must handle the result set chapter 10 © copyright Janson Industries 2011 85 Outstanding POs ▮ Again, pretty simple but it also returns a result set public ResultSet getOutStandingPOs() { if (conn==null) { init();} read("WHERE PaidAmt = 0"); return rs; } ▮ This means the invoking object (POPay) must handle the result set chapter 10 © copyright Janson Industries 2011 86 Outstanding POs ▮ Will test with following main method 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 © copyright Janson Industries 2011 87 chapter 10 © copyright Janson Industries 2011 88 Updating (in TransTable) ▮ Need to update just the PayDate and PaidAmt fields ▮ Needed another statement variable private Statement updateStmt; ▮ In init, created & assigned statement object updateStmt = conn.createStatement(); ▮ Then create two new methods: ▮ One to build the SQL update statement ▮ One to perform the update chapter 10 © copyright Janson Industries 2011 89 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 © copyright Janson Industries 2011 } 90 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 © copyright Janson Industries 2011 91 Assuming we have the data above chapter 10 © copyright Janson Industries 2011 92 For each unpaid PO display PO#, School & PO Date When you click on one... chapter 10 © copyright Janson Industries 2011 93 ...message displayed and list box cleared… chapter 10 © copyright Janson Industries 2011 94 ...the PayDate and PaidAmt are updated chapter 10 © copyright Janson Industries 2011 95 Running again would show that the PO was updated chapter 10 © copyright Janson Industries 2011 96 POPay Frame import import import import import java.awt.Frame; java.awt.event.ItemListener; java.awt.event.WindowListener; java.sql.SQLException; java.awt.Rectangle; import import import import import java.awt.event.ItemEvent; java.awt.event.WindowEvent; java.sql.ResultSet; java.awt.List; 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; 2 visual comps (list & label) & a result set 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) {} chapter 10 © copyright Janson Industries 2011 public void windowOpened(WindowEvent e) {} Window listener methods 97 POPay Constructor public POPay() { super(); TransTable dummyTT = new TransTable(); rs = dummyTT.getOutStandingPOs(); initialize(); } Creates a TransTable object and retrieves outstanding POs chapter 10 © copyright Janson Industries 2011 98 Initialize (in POPay) 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"); Defines label and frame and gets the list this.setVisible(true); this.add(getOutstandingPOLB(), null); this.add(label, null); addWindowListener(this); } chapter 10 © copyright Janson Industries 2011 99 List (in POPay) ▮ Need to add outstanding PO's to the list ▮ Tie an item listener to the list chapter 10 © copyright Janson Industries 2011 100 List (in POPay) RAD generates code to create, size and position 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; chapter 10 © copyright Janson Industries 2011 } Programmer adds listener & loop to retrieve PO info from result set & add to list 101 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 © copyright Janson Industries 2011 102 Looking good! chapter 10 © copyright Janson Industries 2011 103 Item State Changed ▮ 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 chapter 10 © copyright Janson Industries 2011 104 public void itemStateChanged (ItemEvent e) { String selectedPO = outstandingPOLB.getSelectedItem(); int index = 0; Retrieve PO info, get first char, assign to PO# String pONum = String.valueOf(selectedPO.charAt(index)); index++; Point to next char while(!(String.valueOf(selectedPO.charAt(index)). equals(" "))) { pONum = pONum + String.valueOf(selectedPO.charAt(index)); index++; Loop through till a space is encountered – } space means end of the PO# reached TransTable realPO = new TransTable(pONum); realPO.setPOPaid(); Create TransTable and invoke setPOPaid label.setText("PO# " + realPO.getPONum() + " paid"); outstandingPOLB.removeAll(); } Build and display message and clear POs from list © copyright Janson Industries 2011 chapter 10 105 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 © copyright Janson Industries 2011 106 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 © copyright Janson Industries 2011 107 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 © copyright Janson Industries 2011 108 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 © copyright Janson Industries 2011 109 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 © copyright Janson Industries 2011 110 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 © copyright Janson Industries 2011 111 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 © copyright Janson Industries 2011 112 Multiple DBMS Example ▮ 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 chapter 10 © copyright Janson Industries 2011 113 Multiple DBMS Example DBFile conn, url, driver, user, pw, etc. private init(); abstract delete(),write(), update(), read() is a is a AccessFile DB2File OracleFile driver = ("sun. jdbc.odbc. JdbcOdbcDriver") user = pw = driver = ("com. ibm.as400.access .AS400JDBCDriver") user = pw = driver= “oracle .jdbc.driver. OracleDriver”) user = pw = chapter 10 © copyright Janson Industries 2011 114 Database Example ▮ We’ll create an abstract DBFile class to… ▮ Define connection variables // DBFile Abstract classes import java.util.*; import java.sql.*; cannot be abstract class DBFile { instantiated!! Connection conn = null; String url = null; String user, pw; Properties p = new Properties(); String driver = null; public boolean connExists = false; chapter 10 © copyright Janson Industries 2011 115 Database Example ▮ … and to… ▮ Create a common connection method init public 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 © copyright Janson Industries 2011 116 Database Example ▮ … and to: ▮ Enforce CRUD protected protected protected protected protected abstract abstract abstract abstract abstract void void void void void write(); update(String sqlStmt); read(String whereClause); delete(String sqlStmt); getDataFromRS(); } ▮ Protected allow subclasses access ▮ Even if in a different package chapter 10 © copyright Janson Industries 2011 117 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 © copyright Janson Industries 2011 118 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 © copyright Janson Industries 2011 119 DB2File Class ▮ Have to get the correct driver ▮ JTOpen available (on website) or free at: ▮ http://sourceforge.net/projects/jt400/files/JT Open-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 © copyright Janson Industries 2011 120 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 © copyright Janson Industries 2011 121 Database Example DBFile public init(); abstract delete, write, update, read is a AccessFile driver = user = pw = is a TransTable chapter 10 is a Customer © copyright Janson Industries 2011 122 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 © copyright Janson Industries 2011 123 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 © copyright Janson Industries 2011 124 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 chapter 10 void read(String whereClause) © copyright Janson Industries 2011 {... 125 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 © copyright Janson Industries 2011 126 Verify that POPay still works chapter 10 © copyright Janson Industries 2011 127 TransTable Class ▮ If we moved TxTable from Access to DB2 on an IBM Power System… ▮ …just change TransTable to extend DB2File DBFile public init(); abstract delete, write, update, read is a DB2File url= driver = user = pw = is a chapter 10 © copyright Janson Industries 2011 TransTable 128 TransTable DB2 Class // TransTable.java import java.sql.*; public class TransTable extends DB2File{ private Statement stmt; No communication variables to change public TransTable() { init();....} protected void delete(String whereClause) { } “Got around” abstract delete method chapter 10 © copyright Janson Industries 2011 129 TransTable Class ▮ If we moved TxTable from DB2 on an IBM Power System to Oracle… ▮ …just change TransTable to extend OracleFile DBFile public init(); abstract delete, write, update, read is a OracleFile url= driver = user = pw = is a chapter 10 © copyright Janson Industries 2011 TransTable 130 TransTable DB2 Class // TransTable.java import java.sql.*; public class TransTable extends OracleFile{ private Statement stmt; No communication variables to change public TransTable() { init();....} protected void delete(String whereClause) { } chapter 10 © copyright Janson Industries 2011 131 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) chapter 10 Assuming the table was created using this SQL © copyright Janson Industries 2011 132 TransTable Class protected 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"); } } Do table classes or methods have any idea TxTable was moved? chapter 10 © copyright Janson Industries 2011 133 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 © copyright Janson Industries 2011 134 Click Add External Jars... chapter 10 © copyright Janson Industries 2011 135 Drill down to the jtopen/lib folder and select jt400.jar Click Open then OK chapter 10 © copyright Janson Industries 2011 136 jt400.jar added to project chapter 10 © copyright Janson Industries 2011 137 Run POSale, input a new PO chapter 10 © copyright Janson Industries 2011 138 chapter 10 © copyright Janson Industries 2011 139 DB2 Table chapter 10 © copyright Janson Industries 2011 140 In Class Assg ▮ Create a class DispEmp that: ▮ Retrieves the contents of TNTDB.employee ▮ Displays the contents on a frame chapter 10 © copyright Janson Industries 2011 141 DB Problems ▮ If you get a Unhandled exceptions msg: Unhandled exception Type=Segmentation error vmState=0x00040000 J9Generic_Signal_Number=00000004 ExceptionCode=c0000005 ExceptionAddress=738B72D7 ContextFlags=0001003f Handler1=7FEFA0C0 Handler2=7FECC180 InaccessibleAddress=00000000 EDI=00000000 ESI=70B52000 EAX=00000000 EBX=00000000 ECX=00000020 EDX=00000000 EIP=738B72D7 ESP=6F77DDD4 EBP=6F77DDD8 EFLAGS=00010202 GS=0000 FS=003B ES=0023 DS=0023 Module=C:\Windows\WinSxS\x86_microsoft.vc80.crt_1fc8b3b9a1e18e3b_8.0.50727.4927_none_d08a205e442db5b5\MSVCR80.dll Module_base_address=738A0000 Offset_in_DLL=000172d7 Target=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 even JVMDUMP010I System dump written to K:\JavaBookWS\CE\core.20110331.160455.6620.0001.dmp JVMDUMP032I JVM requested Snap dump using 'K:\JavaBookWS\CE\Snap.20110331.160455.6620.0002.trc' in response to an event JVMDUMP010I Snap dump written to K:\JavaBookWS\CE\Snap.20110331.160455.6620.0002.trc JVMDUMP032I JVM requested Java dump using 'K:\JavaBookWS\CE\javacore.20110331.160455.6620.0003.txt' in response to an event JVMDUMP010I Java dump written to K:\JavaBookWS\CE\javacore.20110331.160455.6620.0003.txt chapter 10 © copyright Janson Industries 2011 142 JVMDUMP013I Processed dump event "gpf", detail "". Dumps can be accessed from within RAD chapter 10 © copyright Janson Industries 2011 143 DB Problems ▮ Open the “dump” text file and scroll down to find the stack trace chapter 10 © copyright Janson Industries 2011 144 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 © copyright Janson Industries 2011 145 chapter 10 © copyright Janson Industries 2011 146 The tables are defined as follows: chapter 10 © copyright Janson Industries 2011 147 chapter 10 © copyright Janson Industries 2011 148 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 © copyright Janson Industries 2011 149 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 © copyright Janson Industries 2011 150 chapter 10 Shipment defined as above © copyright Janson Industries 2011 151 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 chapter 10 © copyright Janson Industries 2011 152