Chapter 25

Relational Databases


Chapter Goals

Organizing Database Information

Product Table in a Relational Database

Product Table

SQL

Some SQL Types and Their Corresponding Java Types

SQL Data Type Java Data Type
INTEGER or INT int
REAL float
DOUBLE double
DECIMAL (m, n) Fixed-point decimal numbers with m total digits and n digits after the decimal point; similar to BigDecimal.
BOOLEAN boolean
CHARACTER (n) or CHAR (n) Fixed-length string of length n; similar to String.

SQL Command to Create a Table

CREATE TABLE Product
(
   Product_Code CHAR(11),
   Description CHAR(40),
   Price DECIMAL(10, 2)
)

SQL Command to Add Data to a Database

SQL

A Customer Table

A Customer Table


An Invoice Table

Poor Design for an Invoice Table with Replicated Customer Data


Linking Tables

Two Tables for Invoice and Customer Data

Linking Tables

Primary Keys

Productivity Hint: Avoid Unnecessary Data Replication


Implementing One-to-Many Relationships

Poor Design for Invoice Table with Replicated Columns

Linked Invoice and Item Tables

Sample Database

Self Check

  1. Would a telephone number be a good primary key for a customer table?
  2. In the database of Section 25.1.3, what are all the products that customer 3176 ordered?

Answers

  1. The telephone number for each customer is unique–a necessary requirement for the primary key. However, if a customer moves and the telephone number changes, both the primary and all foreign keys would need to be updated. Therefore, a customer ID is a better choice.
  2. Customer 3176 ordered ten toasters.

Queries

A Sample Database


Simple Query

An Interactive SQL Tool


Selecting Columns

Selecting Subsets

Selecting Subsets

Selecting Subsets

Calculations

Joins

Joins

Joins

Joining Tables without Specifying a Link Condition

SELECT Invoice.Invoice_Number, Customer.Name
   FROM Invoice, Customer

Joining Tables without Specifying a Link Condition

SELECT Invoice.Invoice_Number, Customer.Name
   FROM Invoice, Customer
   WHERE Invoice.Customer_Number = Customer.Customer_Number

Updating and Deleting Data

Updating and Deleting Data

Self Check

  1. How do you query the names of all customers that are not from Alaska or Hawaii?
  2. How do you query all invoice numbers of all customers in Hawaii?

Answers

  1. SELECT Name FROM Customer WHERE State <> 'AK' AND State <> 'HI'
  2. SELECT Invoice.Invoice_Number FROM Invoice, Customer
       WHERE Invoice.Invoice_Number = Customer.Customer_Number
       AND Customer.State = 'HI'

Databases and Privacy


Installing a Database

Installing a Database

JDBC

JDBC Architecture


Testing the JDBC Driver

  1. Find the class path for the driver, e.g.
    c:\mckoi\mkjdbc.jar
  2. Find the name of the driver class that you need to load, e.g.
    com.mckoi.JDBCDriver
  3. Find the name of the database URL that your driver expects
    jdbc:subprotocol:driver-specific data
    jdbc:mckoi://localhost/

Testing the JDBC Driver

  1. Edit the file database.properties and supply
  2. Compile the program as
    javac TestDB.java
  3. Run the program as
    java -classpath driver_class_path;. TestDB database.properties
    java -classpath driver_class_path:. TestDB database.properties

Testing the JDBC Driver: Possible Problems

File TestDB.java

File SimpleDataSource.java

File database.properties

Self Check

  1. After installing a database system, how can you test that it is properly installed?
  2. You are starting a Java database program to connect to the McKoi database and get the following error message:
    Exception in thread "main" java.lang.ClassNotFoundException:
    com.mckoi.JDBCDriver
    What is the most likely cause of this error?

Answers

  1. Connect to the database with a program that lets you execute SQL instructions. Try creating a small database table, adding a record, and selecting all records. Then drop the table again.
  2. You didn't set the class path correctly. The JAR file containing the JDBC driver must be on the class path.

Database Programming in Java: Connecting to the Database

Connecting to the Database

Connecting to the Database

Executing SQL Statements

Executing SQL Statements

Executing SQL Statements

Executing SQL Statements

Executing SQL Statements

Analyzing Query Results

Analyzing Query Results

Analyzing Query Results

Result Set Meta Data

Result Set Meta Data

Result Set Meta Data

File Product.sql

File ExecSQL.java

Self Check

  1. Suppose you want to test whether there are any customers in Hawaii. Issue the statement
    ResultSet result = stat.executeQuery(
          "SELECT * FROM Customer WHERE State = 'HI'");
    Which Boolean expression answers your question?
  2. Suppose you want to know how many customers are in Hawaii. What is an efficient way to get this answer?

Answers

  1. result.hasNext(). If there is at least one result, then hasNext returns true.
  2. ResultSet result = stat.executeQuery(
          "SELECT COUNT(*) FROM Customer WHERE State = 'HI'");
    result.next();
    int count = result.getInt(1);
    Note that the following alternative is significantly slower if there are many such customers.
    ResultSet result = stat.executeQuery(
          "SELECT * FROM Customer WHERE State = 'HI'");
    while (result.next()) count++; // Inefficient

Case Study: A Bank Database

Tables for ATMSimulation


Case Study: A Bank Database

Case Study: A Bank Database

public Customer findCustomer(int customerNumber, int pin)
       throws SQLException
{
   Connection conn = SimpleDataSource.getConnection();
   try
   {
      Customer c = null;
      PreparedStatement stat = conn.prepareStatement(
            "SELECT * FROM BankCustomer WHERE Customer_Number = ?");
      stat.setInt(1, customerNumber);

      ResultSet result = stat.executeQuery();
      if (result.next() && pin == result.getInt("PIN"))
         c = new Customer(customerNumber,
               result.getInt("Checking_Account_Number"),
               result.getInt("Savings_Account_Number"));
      return c;
   }
   finally
   {
      conn.close();
   }
}

Case Study: A Bank Database

Case Study: A Bank Database

public double getBalance()
      throws SQLException
{
   Connection conn = SimpleDataSource.getConnection();
   try
   {
      double balance = 0
      PreparedStatement stat = conn.prepareStatement(
            "SELECT Balance FROM Account WHERE Account_Number = ?");
      stat.setInt(1, accountNumber);

      ResultSet result = stat.executeQuery();
      if (result.next())
         balance = result.getDouble(1);
      return balance;
   }
   finally
   {
      conn.close();
   }
}

Case Study: A Bank Database

public void deposit(double amount)
      throws SQLException
{
   Connection conn = SimpleDataSource.getConnection();
   try
   {
      PreparedStatement stat = conn.prepareStatement(
            "UPDATE Account"
            + " SET Balance = Balance + ?"
            + " WHERE Account_Number = ?");
      stat.setDouble(1, amount);
      stat.setInt(2, accountNumber);
      stat.executeUpdate();
   }
   finally
   {
      conn.close();
   }
}

File Bank.java

File BankAccount.java

Self Check

  1. Why doesn't the Bank class store an array of Customer objects?
  2. Why do the BankAccount methods throw an SQLException instead of catching it?

Answers

  1. The customer data are stored in the database. The Bank class is now merely a conduit to the data.
  2. The methods are not equipped to handle the exception. What could they do? Print an error report? To the console or a GUI window? In which language?