SDSU CS 580 Client-Server
Spring Semester, 2004
JDBC
Previous    Lecture Notes Index    Next    
© 2004, All Rights Reserved, SDSU & Roger Whitney
San Diego State University -- This page last updated 10-Feb-04


References

http://java.sun.com/j2se/1.4/docs/guide/jdbc/index.html Sun's on-line JDBC Tutorial & Documentation


Client/Server Programming with Java and CORBA, Orfali and Harkey, John Wiley and Sons, Inc. 1997

Connector-J, MySql JDBC Driver Documentation, http://www.mysql.com/documentation/connector-j/index.html


PostgreSQL JDBC Documentation, http://www.ca.postgresql.org/users-lounge/docs/7.2/postgres/jdbc.html


Doc 9, JDBC Slide # 2

SQL and Java

Some Jargon

SQL Access Group (SAG) - multivendor "Standards" group

SQL Call Level Interface (CLI)
SAG standard for remote connects to a database

CLI uses drivers to the database

Program uses a driver manager to talk to the driver

The driver is database specific


In 1996 X/Open CLI was adapted by ISO to become ISO 9075-3 Call level Interface



Doc 9, JDBC Slide # 3
Microsoft's Open Database Connectivity (ODBC)
Extension of the SAG CLI

ODBC 2.0 (32 bit) has three conformance levels

23 API calls for basic SQL stuff

19 API calls for large objects (BLOBs) and driver-specific

19 API calls for scrolling (cursors)

ODBC 3.0



Doc 9, JDBC Slide # 4

JDBC

Java Database Connectivity

Sun states
JDBC is a trademark and
Not an abbreviation for Java Database Connectivity

JDBC is a portable SQL CLI written in Java.

Versions of JDBC

JDBC 1.x

Basic SQL functionality



Doc 9, JDBC Slide # 5
JDBC 2.1 Core

Standard part of JDK 1.2

JDBC drivers must implement JDBC 2.x before you can use it

MySQL driver for JDBC 2.x is in pre-beta release

Additional Features
Can change the result of a query locally & in database



Doc 9, JDBC Slide # 6
JDBC 2.0 Package

Now java.sql

Once was optional Java package javax.sql


Access any tabular data (files, spreadsheets)
Make old drivers scrollable & updateable
Wraps JDBC driver for use in GUI


Doc 9, JDBC Slide # 7
JDBC 3.0

java.sql & javax.sql in JDK 1.4

Most advanced features are in javax.sql



Doc 9, JDBC Slide # 8

JDBC Architecture



JDBC driver provides connections to database via drivers

Doc 9, JDBC Slide # 9
JDBC Drivers, JDBC Versions & Java API

java.sql.* is mainly interfaces for JDBC Drivers

The driver for the database determines the actual functionality



Doc 9, JDBC Slide # 10
Sample JDBC Use

import java.sql.*;
public class SampleConnection 
   {
    public static void main (String args[]) throws Exception
      {
      String dbUrl = "jdbc:mysql://rugby.sdsu.edu:8777/test";
      String user = "whitney";
      String password = "mylittleSecret";
      System.out.println("Load Driver!");
      Class.forName("com.mysql.jdbc.Driver");
      Connection rugby;
      rugby = DriverManager.getConnection( dbUrl, user, password);
      Statement getTables = rugby.createStatement();
      ResultSet tableList = 
         getTables.executeQuery("SELECT * FROM name");
      while (tableList.next() )
         System.out.println("Last Name: " + tableList.getString(1) + '\t' + 
                       "First Name: " + tableList.getString( "first_name"));
      rugby.close();
      }
   }

Doc 9, JDBC Slide # 11
DownLoading the MySQl JDBC Driver

http://www.mysql.com/downloads/api-jdbc-stable.html

Contains the jar file mysql-connector-java-3.0.10-stable-bin.jar

Needs to be in your classpath

Implements JDBC 3.0, but some of the advance features are not functional

See the documentation at:

http://www.mysql.com/documentation/connector-j/index.html


Doc 9, JDBC Slide # 12

Using JDBC


Step 1. Load the driver(s)

Step 2. Connect to the database

Step 3. Issue queries and receive results



Doc 9, JDBC Slide # 13
Loading a Driver

The most commonly used way

A well-written JDBC driver is loaded using Class.forName

To load the Oracle driver

import java.sql.*; 
class JdbcTest
{ 
   public static void main (String args [])  throws
                        ClassNotFoundException
   { 
      Class.forName ("oracle.jdbc.OracleDriver");
   }
}

This requires that oracle package be in your path

A properly written driver will register itself with the DriverManager class


Doc 9, JDBC Slide # 14
Loading a Driver

The Recommended Way

Use the command line to specify the driver

java –Djdbc.drivers=org.postgresql.Driver yourProgramName


Makes it easier to change database vendors with out recompiling the code

Long command lines need script to run



Doc 9, JDBC Slide # 15

JDBC Drivers


Java supports four types of JDBC drivers


  1. JDBC-ODBC bridge plus ODBC driver
Java code access ODBC native binary drivers
ODBC driver accesses databases
ODBC drivers must be installed on each client

  1. Native-API partly-Java driver
Java code accesses database specific native binary drivers

  1. JDBC-Net pure Java driver
Java code accesses database via DBMS-independent net protocol

  1. Native-protocol pure Java driver
Java code accesses database via DBMS-specific net protocol


Doc 9, JDBC Slide # 16
JDBC URL Structure

jdbc:<subprotocol>:<subname>

<subprotocol>
Name of the driver or database connectivity mechanism

<subname>
Depends on the <subprotocol>, can vary with vender
If connection goes over Internet subname is to contain net URL
jdbc:mysql://fargo.sdsu.edu:5555/WHITNEYR


ODBC Subprotocol

jdbc:odbc:<data-source-name>[;<attribute-name>=<attribute-value>]*


Examples

jdbc:odbc:qeor7
jdbc:odbc:wombat
jdbc:odbc:wombat;CacheSize=20;ExtensionCase=LOWER
jdbc:odbc:qeora;UID=kgh;PWD=fooey

Doc 9, JDBC Slide # 17
PostgreSQL Subprotocol


jdbc:postgresql:database
jdbc:postgresql://host/database
jdbc:postgresql://host:port/database

MySQL Subprotocol


jdbc:mysql://[host][,failoverhost...][:port]/[database]
[?propertyName1][=propertyValue1][&propertyName2][=propertyValue2]...

hostname defaults to 127.0.0.1
port defaults to 3306

Legal values for properties can be found at:
http://www.mysql.com/documentation/connector-j/index.html#id2800782


Doc 9, JDBC Slide # 18
DriverManager.getConnection - Using JDBC URL

Three forms:

getConnection(URL, Properties) 
getConnection(URL, userName, Password) 
getConnection(URLWithUsernamePassword) 

Form 1
   static String ARS_URL = "jdbc:oracle:@PutDatabaseNameHere";
   DriverManager.getConnection(ARS_URL, "whitney","secret");
Form 2
   DriverManager.getConnection(
      "jdbc:oracle:whitney/secret@PutDatabaseNameHere");
Form 3
   java.util.Properties info = new java.util.Properties();
   info.addProperty ("user", "whitney");
   info.addProperty ("password","secret");
   DriverManager getConnection (ARS_URL ,info );


Doc 9, JDBC Slide # 19
java.sql.DriverManager

Driver related methods

Connecting to a database


Logging/tracing/Debugging
   Print a message to the current JDBC log stream 


Doc 9, JDBC Slide # 20
DataSource

The current recommended way to get a connection is using a DataSource

In theory DataSource supports connection pooling

DataSources are optional in JDBC 2.0

MySql DataSource is a wrapper for DriverManager


Doc 9, JDBC Slide # 21

Queries


      Connection toFargo = 
         DriverManager.getConnection(database, user, password);
      
      Statement namesTable = toFargo.createStatement();
      ResultSet namesFound = 
         namesTable.executeQuery("SELECT * FROM name");

executeUpdate
Use for INSERT, UPDATE, DELETE or SQL that return nothing
executeQuery
Use for SQL (SELECT) that return a result set

execute
Use for SQL that return multiple result sets
Uncommon


Doc 9, JDBC Slide # 22
ExecuteUpdate Example

   public static void main (String args[])  throws Exception
      {
      String dbUrl = "jdbc:mysql://rugby.sdsu.edu:8777/test";
      String user = "whitney";
      String password = "SCECmysql";
      System.out.println("Load Driver!");
      Class.forName("com.mysql.jdbc.Driver");
      Connection rugby;
      rugby = DriverManager.getConnection( dbUrl, user, password);
      Statement getTables = rugby.createStatement();
      int rowsModified = 
         getTables.executeUpdate("UPDATE name 
            SET first_name = 'foo' WHERE last_name='Whitney'");
      System.out.println( "Number of rows modified: " + rowsModified);
      
      rugby.close();
    }


Doc 9, JDBC Slide # 23
ResultSet - Result of a Query

JDBC returns a ResultSet as a result of a query

A ResultSet contains all the rows and columns that satisfy the SQL statement

A cursor is maintained to the current row of the data

The cursor is valid until the ResultSet object or its Statement object is closed

next() method advances the cursor to the next row

You can access columns of the current row by index or name

ResultSet has getXXX methods that:

have either a column name or column index as argument

return the data in that column converted to type XXX


Doc 9, JDBC Slide # 24
getObject

A replacement for the getXXX methods

Rather than

      ResultSet tableList = 
         getTables.executeQuery("SELECT * FROM name");
      String firstName = tableList.getString( 1);

Can use

      ResultSet tableList = 
         getTables.executeQuery("SELECT * FROM name");
      String firstName = (String) tableList.getObject( 1);

getObject( int k) returns the object in the k’th column of the current row

getObject( String columnName) returns the object in the named column


Doc 9, JDBC Slide # 25

SQL Data Types and Java


SQL type
Java type
CHAR
String
VARCHAR
String
LONGVARCHAR
String
NUMERIC
java.math.BigDecimal
DECIMAL
java.math.BigDecimal
BIT
boolean
TINYINT
byte
SMALLINT
short
INTEGER
int
BIGINT
long
REAL
float
FLOAT
double
DOUBLE
double
BINARY
byte[]
VARBINARY
byte[]
LONGVARBINARY
byte[]
DATE
java.sql.Date
TIME
java.sql.Time
TIMESTAMP
java.sql.Timestamp



Doc 9, JDBC Slide # 26
Some Result Set Issues

What happens when we call next() too many times?

What happens if we try to access data before we call next?

In both cases an java.sql.SQLException is thrown

Doc 9, JDBC Slide # 27
Mixing ResultSets

Can't have two active result sets on same statement

Statement namesTable = toFargo.createStatement();
      Connection rugby;
      rugby = DriverManager.getConnection( dbUrl, user, password);
      Statement getTables = rugby.createStatement();
      ResultSet count = 
         getTables.executeQuery("SELECT COUNT(*) FROM name");
      ResultSet tableList = 
         getTables.executeQuery("SELECT * FROM name");
      
      while (tableList.next() )
         System.out.println("Last Name: " + tableList.getObject(1) + '\t' + 
                       "First Name: " + tableList.getObject( "first_name"));
      // Raises java.sql.SQLException
      count.getObject(1);
      rugby.close();

this can happen two threads have access to the same statement


Doc 9, JDBC Slide # 28
Two Statements on one Connection work

      Connection rugby;
      rugby = DriverManager.getConnection( dbUrl, user, password);
      Statement getTables = rugby.createStatement();
      Statement tableSize = rugby.createStatement();
      ResultSet count = 
         getTables.executeQuery("SELECT COUNT(*) FROM name");
      ResultSet tableList = 
         tableSize.executeQuery("SELECT * FROM name");
      
      while (tableList.next() )
         System.out.println("Last Name: " + tableList.getObject(1) + '\t' + 
                       "First Name: " + tableList.getObject( "first_name"));
      count.next();
      System.out.println("Count: " + count.getObject(1) );
      count.close();
      tableList.close();
      rugby.close();

Doc 9, JDBC Slide # 29

Threads & Connections


Some JDBC drivers are not thread safe

If two threads access the same connection results may get mixed up

PostgreSQL & MySql drivers are thread safe

When two threads make a request on the same connection



Can use more than one connection but



Doc 9, JDBC Slide # 30

Transactions


A transaction consists of one or more statements that have been executed and completed

A transaction ends when a commit or rollback is sent

Connections are opened in auto commit mode:

when a statement is completed, it is committed


Transactions and Concurrency

What happens to data that is changed in a transaction, but not yet committed?

Can other programs access the old or new values?

Use setTransactionIsolation(int) in Connection class to set access levels

Access levels are given as static fields of Connection class

TRANSACTION_NONE
TRANSACTION_READ_COMMITTED
TRANSACTION_READ_UNCOMMITTED
TRANSACTION_REPEATABLE_READ
TRANSACTION_SERIALIZABLE


Doc 9, JDBC Slide # 31
Transaction Example

import java.sql.*; 
public static void main (String args[])  throws Exception
      {
      String dbUrl = "jdbc:mysql://rugby.sdsu.edu:8777/test";
      String user = "whitney";
      String password = "SCECmysql";
      System.out.println("Load Driver!");
      Class.forName("com.mysql.jdbc.Driver");
      
      Connection rugby;
      rugby = DriverManager.getConnection( dbUrl, user, password);
      rugby.setAutoCommit(false);
      Statement update  = rugby.createStatement();
      update.executeUpdate("INSERT INTO name 
            (first_name, last_name) VALUES ( 'Donald', 'Duck') ");
      update.executeUpdate("INSERT INTO name 
            (first_name, last_name) VALUES ( 'Micky', 'Mouse') ");
      rugby.rollback();
      update.close();
      Statement getTables  = rugby.createStatement();
      ResultSet tableList = 
         getTables.executeQuery("SELECT * FROM name");
      while (tableList.next() )
         System.out.println("Last Name: " + tableList.getObject(1) + '\t' + 
                       "First Name: " + tableList.getObject( "first_name"));
      rugby.close();
    }

Doc 9, JDBC Slide # 32
MySql & Transactions

Note that MySql does not support transactions unless it is a recent version and is configured to do so.


There is a test to see if the database supports transactions

However, it did return the incorrect answer when I tested the code


      Connection rugby;
      rugby = DriverManager.getConnection( dbUrl, user, password);
      rugby.setAutoCommit(false);
      boolean hasTransactions = 
         ((com.mysql.jdbc.Connection)rugby).supportsTransactions();
      System.out.println( "Supports transctions? " + hasTransactions);


Doc 9, JDBC Slide # 33

PreparedStatement


PreparedStatement objects contain SQL statements that have been sent to the database to be prepared for execution

The SQL statements contains variables (IN parameters) which are given values before statement is executed

Only makes sense to use if database and driver keeps statements open after they have been committed

IN parameters are indicated by a ?

Values are set by position

String flightOut =    "SELECT * FROM AirlineSchedule 
            WHERE from = ?";



Doc 9, JDBC Slide # 34
PreparedStatement Example

import java.sql.*; 
import java.io.*; 
      Connection rugby;
      rugby = DriverManager.getConnection( dbUrl, user, password);
      
      String findPerson = 
         "SELECT * FROM name WHERE last_name = ?";
      PreparedStatement  find  = rugby.prepareStatement( findPerson );
      find.setObject( 1, "whitney" );
      ResultSet person =  find.executeQuery();
      while (person.next() )
         System.out.println("Last Name: " + person.getObject(1) + '\t' + 
                       "First Name: " + person.getObject( "first_name"));
      find.clearParameters();
      find.setObject( 1, "olson" );
      person = find.executeQuery();
      while (person.next() )
         System.out.println("Last Name: " + person.getObject(1) + '\t' + 
                       "First Name: " + person.getObject( "first_name"));
      rugby.close();

Works in MySql

Doc 9, JDBC Slide # 35

Batch Updates


Allows one to send a batch of updates in one request

   Connection rugby;
   rugby = DriverManager.getConnection( dbUrl, user, password);
      
   Statement  batch  = rugby.createStatement();
   batch.addBatch("INSERT INTO name (first_name, last_name) 
            VALUES ('Lion', 'King')");
   batch.addBatch("INSERT INTO name (first_name, last_name) 
            VALUES ('Little', 'Nemo')");
   int[] updates = batch.executeBatch();
   for( int k = 0; k < updates.length;k++)
      System.out.println( "Update " + k + " rows affected " + updates[k]);
   rugby.close();


Doc 9, JDBC Slide # 36

CallableStatement


Some databases have stored procedures (a procedure of SQL statements)

CallableStatement allows a Java program to invoke a stored procedure in a database



DatabaseMetaData

The class DatabaseMetaData allows you to obtain information about the database

The 113 methods in DatabaseMetaData give you more information than you thought possible

Copyright ©, All rights reserved.
2004 SDSU & Roger Whitney, 5500 Campanile Drive, San Diego, CA 92182-7700 USA.
OpenContent license defines the copyright on this document.

Previous    visitors since 10-Feb-04    Next